Errors and warnings are a clear sign that a script is not working correctly. While sometimes just seeing the error message is enough to know how to fix the problem, that is not always the case.
debug.error
, debug.warning
, and debug.type.changes
are three functions to help a user understand an error and what portions of the script led to the error.
debug.error
and debug.warning
both provide information on the backwards lineage of an error or warning message produced by R. The backward lineage contains the lines of code that led either directly or indirectly to computing a value that is used on the line that produced the error.
Let myScript.R
be the following:
x <- 1
y <- 2
x <- a + x
Running this script will result in the following error since no value has been assigned to a:
Error in eval(annot, environ, NULL) : object 'a' not found
The result of debug.error()
is:
Your Error: Error in eval(annot, environ, NULL): object 'a' not found
Code that led to error message:
scriptNum scriptName startLine code
1 1 myScript.R 1 x <- 1
2 1 myScript.R 3 x <- a + x
This shows that lines 1 and 3 may have contributed to the error. Notice that line 2 is not shown. It is not part of the lineage of the statement that resulted in the error, since statement 3 neither uses y
nor any other variable that itself depends on y
.
The data frame returned by debug.error
contains the following columns:
scriptNum
The script number the error is associated with.scriptName
The name of the script the error is associated with.startLine
The line number the error is reported oncode
The line of code which resulted in the error.debug.warning
similarly displays the lineage of a warning message, although it does not currently support the connection with Stack Overflow, which is discussed below.
The function signature for debug.error
is:
debug.error(stack.overflow = FALSE)
The parameter for this function is:
stack.overflow
If TRUE, the error message will be searched for on Stack Overflow.This function may be called only after initialising the debugger using either prov.debug
, prov.debug.run
, or prov.debug.file
. For example:
prov.debug.run("myScript.R")
debug.error()
debug.error(stack.overflow = TRUE)
When TRUE is passed in for the stack.overflow parameter, in addition to returning the backwards lineage of the error, the error will also be searched on Stack Overflow. The user will be presented with the titles of the top 6 matching search results. The user can then select one or more of these and a browser window will open displaying the corresponding Stack Overflow page.
The result of debug.error(stack.overflow = TRUE)
is:
Your Error: Error in eval(annot, environ, NULL): object 'a' not found
Code that led to error message:
scriptNum scriptName startLine code
1 1 myScript.R 1 x <- 1
2 1 myScript.R 3 x <- a + x
Results from StackOverflow:
1. "Object not found error with ddply inside a function"
2. "ggplot object not found error when adding layer with different data"
3. "Error in eval(expr, envir, enclos) : object not found"
4. "data.table throws \"object not found\" error"
5. "Object not found error when passing model formula to another function"
6. "Object not found error with ggplot2"
Choose a numeric value that matches your error the best or q to quit:
debug.type.changes
is also intended to help users resolve errors.
In this case, it is intended to help with a specific error in which a variable is bound to a new value and that new value has a different type. Since R is not a type-checked language, these errors can easily creep into a program and can be hard to debug. For example, this can occur if a variable name gets reused for a different purpose, or if a vectorizing operation changes a variable from a single scalar value to a long vector unexpectedly.
Consider this simple example:
a <- 1
<code omitted>
a <- a + b
If the programmer thought that b was an integer and instead it was a longer vector, they might have expected that they were simply adding two integers together. However, now the type of a
has changed from a vector of length 1 to a vector as long as the vector referenced by b.
Calling debug.type.changes()
will show all variables whose type has changed, what those values were, and where the changes occurred, as shown here:
$a
value container dimension type code scriptNum scriptName startLine
1 1 vector 1 numeric a <- 1 1 1 typechanges.R 1
2 2 3 4 5 6 7 8 9 10 11 vector 10 numeric a <- a + b 2 1 typechanges.R 3