Using R — Easier Error Handling with try()

This entry is part 6 of 22 in the series Using R

In a previous post we looked at error handling in R with the tryCatch() function and how this could be used to write Java style try-catch-finally blocks. This time we’ll look at what can be done with the try() function and how we can easily process warning and error messages to take appropriate action when something goes wrong.

The try() function is really just a simplified interface to tryCatch(). To see how try() calls tryCatch() you can examine the guts of the try() function by typing try [without parens] at the R prompt but you may not like what you see. For those of us outside the R core development team, this is not a good place to start. The ?try documentation is much better and has a useful example showing how try() can be used to generate simulated results, ignoring those that generated errors. But this documentation doesn’t address the kind of error handling one needs for ‘business logic’ where different actions are taken depending on the kind of error issued.

For this post, we will more generally explore how try() can be used and how warning and error messages can be processed using geterrmessage() and grepl(). The important things to remember about these functions are:

  • try() only ignores warnings, not errors
  • options(warn=2) turns warnings into errors
  • geterrmessage() returns the character string associated with the last error
  • grepl(pattern, string) returns TRUE if ‘pattern’ if found within ‘string’, FALSE otherwise

With just these functions we have everything we need to write very simple constructs that can evaluate a function and handle both errors and warnings. The test script at the end of this post demonstrates how messages and errors can be generated within a function and then trapped and processed by a calling function, potentially generating new errors that could be passed upstream. Just copy and paste the script at the end, make it executable and try it out with the these shell commands:

$ chmod +x try.Rscript
$ try.r 2
$ try.r 1
$ try.r 0
$ try.r a
$ try.r
$ try.r warning
$ try.r error-A
$ try.r error-B

And here is the script.

#!/usr/bin/env Rscript
# try.Rscript -- experiments with try

# Get any arguments
arguments <- commandArgs(trailingOnly=TRUE)
a <- arguments[1]

# Define a function that can issue custom warnings and errors
# Use '.call=FALSE' to remove the function call from the message
myFunc <- function(a) {
  if (a == 'warning') {
  return_value <- 'warning return'
  warning("custom warning message", call.=FALSE)
} else if (a == 'error-A') {
  return_value <- 'error return'
  stop("custom error message A", call.=FALSE)
} else if (a == 'error-B') {
  return_value <- 'error return'
  stop("custom error message B", call.=FALSE)
} else {
  return_value = log(a)

# Turn warnings into errors so they can be trapped
options(warn = 2)
result <- try(myFunc(a), silent=TRUE)

# Process any error messages
if (class(result) == "try-error") {
  # Ignore warnings while processing errors
  options(warn = -1)

  # If this script were a function, warning() and stop()
  # could be called to pass errors upstream
  msg <- geterrmessage()
  if (grepl("missing value", msg)) {
    result <- paste("USER ERROR: Did you supply an argument?")
  } else if (grepl("Non-numeric argument",msg)) {
    # Oops, forgot to convert argument to numeric
    a <- as.numeric(a)
    if ( {
      result <- "Argument is non-numeric"
    } else {
      result <- myFunc(a)
  } else if (grepl("custom warning message", msg)) {
    result <- "Took action for warning message"
  } else if (grepl("custom error message A", msg)) {
    result <- "Took action for error message A"
  } else if (grepl("custom error message B", msg)) {
    result <- "Could call stop() to pass an error upstream."

  # Restore default warning reporting

Series NavigationUsing R — Package Installation ProblemsUsing R — Calling C Code ‘Hello World!’
This entry was posted in R and tagged , . Bookmark the permalink.

Comments are closed.