When writing R code for use in production systems, it is important to enclose chunks of code inside of try() blocks. This is especially important when processing user input or data obtained from web services which may fail for a variety of reasons. If any problems arise within a try() block, it is important to generate informative and consistent error messages.

Over the years, we have developed our own standard protocol for error handling that is easy to understand, easy to implement, and allows for consistent generation of error messages. To goal is to make it easy for developers to test sections of code that might fail and to create more uniform, more informative error messages than those that might come from deep within the R execution stack.

In addition to the generation of custom error messages, use of prefix allows for the creation of classes of errors that can be detected and handled appropriately as errors propagate to other functions.

stopOnError(
  result,
  err_msg = "",
  prefix = "",
  maxLength = 500,
  truncatedLength = 120,
  call. = FALSE
)

Arguments

result

Return from a try() block.

err_msg

Custom error message.

prefix

Text string to add in front of the error message.

maxLength

Maximum length of an error message. Error messages beyond this limit will be truncated.

truncatedLength

Length of the output error message.

call.

Logical indicating whether the call should become part of the error message.

Value

Issues a stop() with an appropriate error message.

Note

If logging has been initialized, the customized/modified error message will be logged with logger.error(err_msg) before issuing stop(err_msg).

The following examples show how to use this function:


library(MazamaCoreUtils)

# Arbitrarily deep in the stack we might have:

myFunc <- function(x) {
  a <- log(x)
}


# Simple usage

userInput <- 10
result <- try({
  myFunc(x = userInput)
}, silent = TRUE)
stopOnError(result)

userInput <- "ten"
result <- try({
  myFunc(x = userInput)
}, silent = TRUE)
stopOnError(result)


# More concise code with the '%>%' operator

try({
  myFunc(x = userInput)
}, silent = TRUE) %>%
stopOnError(err_msg = "Unable to process user input")

try({
  myFunc(x = userInput)
}, silent = TRUE) %>%
stopOnError(prefix = "USER_INPUT_ERROR")


# Truncating error message length

try({
  myFunc(x = userInput)
}, silent = TRUE) %>%
stopOnError(
  prefix = "USER_INPUT_ERROR",
  maxLength = 40,
  truncatedLength = 32
)