There are three types of R error messages: errors, warnings and messages. These are ‘thrown’ with `stop()`

, `warning()`

and `message()`

respectively.

`stop("This isn't working.")`

`## Error: This isn't working.`

`warning("I'm not sure about this")`

`## Warning: I'm not sure about this`

`message("By the way...")`

`## By the way...`

Some error messages are quite informative:

`rnorm("hello")`

`## Warning: NAs introduced by coercion`

`## Error: invalid arguments`

Some are less so.

```
f = function(lambda, dat) sum(dat*log(lambda) - lambda)
y = rpois(100, lambda=2)
newton(f, start=1, dat=y)
```

`## Warning: NaNs produced`

`## Error: missing value where TRUE/FALSE needed`

When you write code try to make your messages as specific and as helpful as possible!

The most powerful way to find out what’s gone wrong is to ‘step in’ to the function at the point of failure.

`options(error=recover)`

When your function throws an error, you’ll be presented with a call stack, and you can select any environment to enter into. My advice is to start in the deepest environment containing code which you wrote yourself.

In the case below (we’re calling the code from the profiling page) you don’t have a choice: press ‘1’ to step inside your function.

```
> newton(f, start=1, dat=y)
Error in while (max(abs(FUN(x, ...))) > tol) { :
missing value where TRUE/FALSE needed
In addition: Warning message:
In log(lambda) : NaNs produced
Enter a frame number, or 0 to exit
1: newton(f, start = 1, dat = y)
Selection:
```

To get back just press enter and you’ll return to this menu; 0 exits completely.

A warning is usually an indication that something is wrong, even if it hasn’t generated a full blown error, so don’t ignore them! For debugging purposes it’s useful to set

`options(warn=2)`

which turns warnings straight into errors (the default is 0).

```
> newton(f, start=1, dat=y)
Error in log(lambda) : (converted from warning) NaNs produced
Enter a frame number, or 0 to exit
1: newton(f, start = 1, dat = y)
2: #4: FUN(x, ...)
3: #1: .signalSimpleWarning("NaNs produced", quote(log(lambda)))
4: withRestarts({
.Internal(.signalCondition(simpleWarning(msg, call), msg, call))
.Int
5: withOneRestart(expr, restarts[[1]])
6: doWithOneRestart(return(expr), restart)
Selection:
```

If you step into frame number 2 (which is the function `f`

being called) we can check what the `dat`

and `lambda`

are:

```
Browse[1]> lambda
[,1]
[1,] -0.6477124
```

So `f`

was called with inappropriate arguments. If we step out of this frame and back to frame 1…

```
Browse[2]> x
[,1]
[1,] -0.6477124
```

Now we see the problem: we stepped outside the valid range of our function.

In order to make `newton()`

deal with this problem, we have to allow it to *handle* an error given to it by the function `FUN`

.

```
## step()
##' Obtain one step of a Newton algorithm
##'
##' @param FUN function taking single vector argument
##' @param x current value of argument to \code{FUN}
##' @param eps length of step size used for calculating numerical derivative
##'
##' @return numeric vector giving next \code{x} value
step = function(FUN, x, ..., eps = 1e-8) {
val = FUN(x, ...)
deriv = matrix(NA, length(val), length(val))
for (i in 1:length(val)) {
eps_vector = rep(0, length(val))
eps_vector[i] = eps
deriv[,i] = (FUN(x + eps_vector, ...) - FUN(x, ...)) / eps
}
out = -solve(deriv) %*% val
return(out)
}
## newton()
##' Run Newton algorithm to find root of function
##'
##' @param FUN function taking single vector argument
##' @param start starting value of argument to FUN
##' @param tol maximum value of function for convergence
##' @param eps length of step size used for calculating numerical derivative
##'
##' @return numeric vector of point achieved after convergence
##' of the Newton algorithm
newton = function(FUN, start, ..., tol = 1e-8, eps = 1e-8) {
x = start
val = tryCatch(FUN(x, ...),
error = function(e) stop("Invalid starting value for FUN")
)
while (max(abs(val)) > tol) {
move = step(FUN, x, ..., eps=eps)
x = x + move
val = tryCatch(FUN(x, ...),
error = function(e) stop("Moved outside valid range")
)
}
return(x)
}
newton(f, start=2, dat=y)
```

`## Warning: NaNs produced`

`## Error: missing value where TRUE/FALSE needed`

At this point you might notice that the function `f`

I keep passing is the log-likelihood, but I should be giving the *derivative* of the log-likelihood. Hence:

```
Df = function(lambda, dat) sum(dat/lambda - 1)
newton(Df, start=1, dat=y)
```

```
## [,1]
## [1,] 1.82
```

And now it works!

Sometimes the traceback doesn’t help, because the problem occurred before an error was thrown. If you call `debug()`

on a function, you can ‘step through’ the function as it runs line-by-line, and see what it’s doing at each stage.

```
debug(lm)
x = rnorm(20); y = x+rnorm(20)
lm(y ~ x)
```

There are some special commands you can use: `f`

will ‘finish’ the current loop; `s`

allows you to step into the function calls in the next statement, again using the browser. `Q`

finishes all executions and gets you back to the ordinary command line.

Run `undebug(lm)`

(or equivalent) to stop this behaviour.

The `trace()`

function provides a principled way of adding (for example) print statements to your code, without actually modifying it permanently. The most intuitive way to do this is with the `edit=TRUE`

option, which gives you an editor containing a copy of your function. Any changes you make here will not alter your real code, so you can play around as you like. This version of the function will be run until you redeine your function, or call `untrace()`

.

```
trace(lm, edit=TRUE)
# try adding a print statement or two
```