I want to improve the R error handling by providing a function to handle specific (selected) conditions combined with a retry feature.
For example looped downloads should retry after timeouts or connection errors but stop immediately in case of other errors.
I cannot find a reliable way to identify a specific condition.
With "reliable" I mean something like a condition ID or at least different condition classes. My problem is:
Error conditions thrown by base R (and also many packages using
stop
) seem not to use sub classes but (almost) always returnsimpleError
,error
andcondition
asclass
.Error messages may be localized (different languages) and could even change over time with new releases.
How can I reliably recognize a specific condition of base R or 3rd party packages independently of the R versions, platform (Win, OSX, Linux) and language setting?
I assume that I cannot modify the source code that throws the conditions (e. g. to add a sub class).
examine_condition <- function(exp) {
cnd <- tryCatch(exp, error = function(e) e)
str(cnd) # show the internals
invisible(cnd)
}
examine_condition(base::log("a"))
# List of 2
# $ message: chr "non-numeric argument to mathematical function"
# $ call : language log("a")
# - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
examine_condition(base::colSums("a"))
# List of 2
# $ message: chr "'x' must be an array of at least two dimensions"
# $ call : language base::colSums("a")
# - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
examine_condition(utils::read.csv(file = "this file does not exist.csv"))
# List of 2
# $ message: chr "cannot open the connection"
# $ call : language file(file, "rt")
# - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
examine_condition(stop("my error"))
# List of 2
# $ message: chr "my error"
# $ call : language doTryCatch(return(expr), name, parentenv, handler)
# - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
library(data.table)
data <- as.data.frame(mtcars)
examine_condition(data[, new_col := 99]) # ":=" is data.table syntax!
# List of 2
# $ message: chr "Check that is.data.table(DT) == TRUE. Otherwise, := and `:=`(...) are defined for use in j, once only and in pa"| __truncated__
# $ call : language `:=`(new_col, 99)
# - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
See also: