tryCatch
tryCatch(expr, ..., finally) Introduction
tryCatch() is R’s primary mechanism for handling conditions such as errors, warnings, and messages. It evaluates an expression and routes any raised condition to the appropriate handler function you provide. Without any handlers, tryCatch() simply evaluates expr and returns the result — making it also useful as a mechanism for guaranteeing cleanup via the finally argument.
The function signature is:
tryCatch(expr, ..., finally)
expris the expression to evaluate....accepts named handler functions:error,warning,message, andcondition.finallyis a single expression evaluated regardless of whether a condition was raised.
Handling Errors
The most common use case is catching errors and returning a fallback value. The error handler receives a condition object with at least $message and $call components.
safe_log <- function(x) {
tryCatch(
expr = log(x),
error = function(cnd) {
message("Error: ", cnd$message)
NA_real_
}
)
}
safe_log(10)
# [1] 2.302585
safe_log("hello")
# Error: non-numeric argument to mathematical function
# [1] NA
The handler function returns the value that tryCatch() will ultimately return. Here, NA_real_ replaces the error, letting the caller proceed without crashing.
The finally Block
finally is evaluated after expr completes (or after a handler returns) and is useful for cleanup tasks like closing file connections or resetting options. Its return value is ignored.
read_first_line <- function(path) {
conn <- NULL
tryCatch(
expr = {
conn <- file(path, open = "r")
readLines(conn, n = 1)
},
error = function(cnd) NA_character_,
finally = {
if (!is.null(conn)) close(conn)
}
)
}
# Connection is closed whether readLines() succeeds or fails
finally runs even if the handler itself throws an error. The cleanup happens before that error propagates upward.
Handling Warnings
Warnings are trickier than errors. By default, execution of expr continues after a warning is signalled — the warning handler is called only after expr finishes. If you want to stop on the first warning, set options(warn = 1) beforehand.
result <- tryCatch(
expr = suppressWarnings(as.numeric(c("1", "2", "three"))),
warning = function(cnd) {
message("Warning caught: ", cnd$message)
NA_real_
}
)
result
# [1] 1 2 NA
Using suppressWarnings() inside expr is a common pattern when you want to both handle and suppress a warning in one call.
Handler Return Values
When a handler does not explicitly call return(), it returns NULL invisibly. This is easy to miss:
x <- tryCatch(
expr = stop("oops"),
error = function(cnd) {
# no explicit return — returns NULL invisibly
message("Caught: ", cnd$message)
}
)
x
# [1] NULL
print(x)
# NULL
Always return a value explicitly from handlers if you need a specific result.
Multiple Handlers
You can supply handlers for different condition types simultaneously. Each handler only fires for its corresponding type.
result <- tryCatch(
expr = {
x <- log(-1) # produces a warning, execution continues
if (x < 0) stop("Negative value from log")
x
},
warning = function(cnd) {
message("Warning: ", cnd$message)
NA_real_
},
error = function(cnd) {
message("Error: ", cnd$message)
NA_real_
}
)
# Warning: NaNs produced
# Error: Negative value from log
# [1] NA
The warning fires first (after expr completes), then the subsequent stop() triggers the error handler. Both return NA_real_, so the final result is NA.
Condition Object Structure
Handlers receive a condition object with these key components:
condition <- function(cnd) {
cnd$message # character string of the condition message
cnd$call # the call that triggered the condition (NULL if call. = FALSE)
class(cnd) # e.g. c("error", "condition") or c("warning", "condition")
}
You can inspect the class to branch logic within a generic condition handler, though specific handlers like error and warning are usually clearer.
When tryCatch() Is Not the Right Tool
For simply silencing output, suppressWarnings() and suppressMessages() are shorter and more direct. For re-throwing errors after logging, call stop() inside the error handler. For lower-level control over the call stack, look at withCallingHandlers().
See Also
is.na()— Test for missing valuesis.null()— Test for NULL valuesifelse()— Conditional element selection
Summary
tryCatch() wraps an expression and lets you respond to errors, warnings, and messages through handler functions. The finally argument guarantees cleanup runs regardless of what happens. Handlers receive condition objects you can inspect for the message text, call, and condition class. When a handler returns a value, that becomes tryCatch()’s return value — unless the handler itself throws, in which case finally still runs first. For simple suppression, use suppressWarnings() or suppressMessages() instead.