16

Sometimes R throws me errors such as

Error in if (ncol(x) != 2) { : argument is of length zero

with no additional information, when I've written no such code. Is there a general way for finding which function in which package causes an error?

Since most packages come compressed, it isn't trivial to grep /usr/lib/R/library.

MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
Tim
  • 13,904
  • 10
  • 69
  • 101
  • I find the easiest way to debug is to step through the code line by line. If your error is coming from a function you wrote, you can debug it using `debugonce(function_name)`. This will give you a mini R session inside the scope of the function. – Justin Nov 19 '12 at 14:31
  • That's what I've been doing, but I feel like I spend too much time on something that could be automated. – Tim Nov 19 '12 at 14:33

2 Answers2

21

You can use traceback() to locate where the last error occurred. Usually it will point you to a call you make in your function. Then I typically put browser() at that point, run the function again and see what is going wrong.

For example, here are two functions:

f2 <- function(x)
{
  if (x==1) "foo"
}

f <- function(x)
{
  f2(x)
}

Note that f2() assumes an argument of length 1. We can misuse f:

> f(NULL)
Error in if (x == 1) "foo" : argument is of length zero

Now we can use traceback() to locate what went wrong:

> traceback()
2: f2(x) at #3
1: f(NULL)

The number means how deep we are in the nested functions. So we see that f calls f2 and that gives an error at line 3. Pretty clear. We could reassign f with browser placed just before the f2 call now to check it's input. browser() simply allows you to stop executing a function and look around in its environment. Similar to debug and debugonce except that you don't have to execute every line up until the point you know something goes wrong.

Sacha Epskamp
  • 46,463
  • 20
  • 113
  • 131
19

Just to add to what @SachaEpskamp has already suggested, setting options(error=recover) and options(show.error.locations=TRUE) can be extremely helpful when debugging unfamiliar code. The first causes R to launch a debugging session on error, giving you the option to invoke the browser at any point in the call stack up to that error. The second option will tell R to include the source line number in the error.

Matthew Plourde
  • 43,932
  • 7
  • 96
  • 113
  • 2
    additionally, if you set `options(warn=2)` then the same will occur upon a warning, which can be useful if you end up having factors converted to numbers incorrectly (inducing `NA`, which is typically not what you want – richiemorrisroe Nov 19 '12 at 19:36
  • So set my options to options(error=recover), options(show.error.locations=TRUE), and options(warn=2), but would like to reset these options to their original state. How would I do that? – stochasticcrap Mar 11 '15 at 20:34
  • 2
    `o <- options(error=recover, show.error.locations=TRUE, warn=2);#do stuff;do.call(options, o) # reset` Feel free to upvote if this answer helped you. – Matthew Plourde Mar 11 '15 at 20:38