tryCatch() for Error Recovery
Catch and handle errors, warnings, and messages with tryCatch().
tryCatch() for Error Recovery is a free R Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the R Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What is tryCatch()?
tryCatch() lets you run an expression and intercept any conditions (errors, warnings, messages) that it signals. If the expression succeeds, its value is returned. If it signals a condition, the matching handler is called instead.
result <- tryCatch({
sqrt(16)
}, error = function(e) {
NA
})
cat('Result:', result, '\n')Catching an Error
When the expression inside tryCatch() calls stop(), execution jumps to the error handler. The handler receives the condition object and returns its value as the result of the whole tryCatch() call.
safe_divide <- function(x, y) {
tryCatch({
if (y == 0) stop('division by zero')
x / y
}, error = function(e) {
cat('Caught error:', conditionMessage(e), '\n')
NA
})
}
cat(safe_divide(10, 2), '\n')
cat(safe_divide(10, 0), '\n')Catching a Warning
The warning handler works the same way as error, but intercepts warning conditions. Note: once a warning handler is defined in tryCatch(), warnings cause a non-local exit just like errors — execution does not resume after the warning.
result <- tryCatch({
log(-1)
}, warning = function(w) {
cat('Warning caught:', conditionMessage(w), '\n')
-999
})
cat('Result:', result, '\n')Catching a Message
You can also catch message() conditions. This lets you intercept and reformat informational output from functions you do not control. The handler receives the condition object, and the message's text includes a trailing newline.
result <- tryCatch({
message('Loading data...')
42
}, message = function(m) {
cat('Intercepted message:', trimws(conditionMessage(m)), '\n')
-1
})
cat('Result:', result, '\n')The finally Clause
The finally block always runs after the expression — whether it succeeded, errored, or warned. Use it for cleanup code like closing connections, resetting options, or logging completion.
result <- tryCatch({
cat('Trying...\n')
stop('oops')
}, error = function(e) {
cat('Handled:', e$message, '\n')
-1
}, finally = {
cat('Finally block always runs\n')
})
cat('Result:', result, '\n')Multiple Handlers
You can supply handlers for multiple condition types in a single tryCatch() call. R matches the first applicable handler. If both error and warning handlers are defined, warnings are caught before they can become errors.
handle_it <- function(expr_result) {
tryCatch(expr_result,
error = function(e) paste('ERROR:', e$message),
warning = function(w) paste('WARN:', w$message),
message = function(m) paste('MSG:', trimws(m$message))
)
}
cat(handle_it(stop('bad input')), '\n')
cat(handle_it(log(-1)), '\n')Error Recovery in a Loop
A very practical pattern: wrap the body of a loop in tryCatch() so that one failed iteration does not stop the entire loop. This is essential when processing files, API calls, or user inputs that may fail unpredictably.
inputs <- list(4, -1, 0, 16, 'x')
results <- vector('list', length(inputs))
for (i in seq_along(inputs)) {
results[[i]] <- tryCatch(
sqrt(as.numeric(inputs[[i]])),
warning = function(w) NA,
error = function(e) NA
)
}
cat('Results:', unlist(results), '\n')Returning Meaningful Defaults on Error
A clean pattern is to return a sensible default value from the error handler. The handler's return value becomes the result of tryCatch(). Returning NA, NULL, 0, or a default list all work well.
safe_parse <- function(x) {
tryCatch(
as.numeric(x),
warning = function(w) {
cat('Cannot parse:', x, '-> using 0\n')
0
}
)
}
cat(safe_parse('3.14'), '\n')
cat(safe_parse('abc'), '\n')
cat(safe_parse('99'), '\n')Extracting the Error Message
Inside an error handler, use conditionMessage(e) or the shorthand e$message to get the error text. Use conditionCall(e) or e$call to get the call that triggered it.
tryCatch(
stop('file not found: data.csv'),
error = function(e) {
cat('Message:', conditionMessage(e), '\n')
cat('Class :', paste(class(e), collapse=', '), '\n')
}
)tryCatch() vs try()
R also has the simpler try(expr) function. On error it returns a 'try-error' class object instead of halting. Use try() for quick one-liners; use tryCatch() when you need full handler control or a finally block.
# try() returns try-error object on failure
result <- try(log('x'), silent = TRUE)
if (inherits(result, 'try-error')) {
cat('try() caught error\n')
} else {
cat('Result:', result, '\n')
}Nesting tryCatch() Calls
tryCatch() calls can be nested. An inner tryCatch() catches conditions first; if it re-throws (using stop(e)), the outer handler catches the re-thrown condition.
outer_result <- tryCatch({
tryCatch({
stop('inner error')
}, error = function(e) {
cat('Inner handler, re-throwing\n')
stop(paste('Wrapped:', e$message))
})
}, error = function(e) {
cat('Outer handler:', e$message, '\n')
'recovered'
})
cat('Final:', outer_result, '\n')Quick Check
In tryCatch(), which clause always runs regardless of whether an error occurred or not?
tryCatch(): Key Takeaways
Key takeaways for tryCatch():
- Intercept errors with
error = function(e) {...}, warnings withwarning = function(w) {...} - The handler's return value becomes the result of
tryCatch() finallyalways executes — ideal for cleanup- Wrap loop bodies in
tryCatch()for robust iteration over unreliable inputs e$messageorconditionMessage(e)extracts the error texttry(expr, silent=TRUE)is a simpler one-liner alternative
safe_op <- function(x) {
tryCatch({
if (!is.numeric(x)) stop('not numeric')
sqrt(x)
}, error = function(e) {
cat('Error:', e$message, '\n')
NA
}, finally = {
cat('Done processing', x, '\n')
})
}
cat(safe_op(9), '\n')
cat(safe_op('a'), '\n')Frequently asked questions
Is the “tryCatch() for Error Recovery” lesson free?
Yes — the full text of “tryCatch() for Error Recovery” is free to read here on the web, and the R Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the R Academy course, upgrade to CoddyKit PRO.
What will I learn in “tryCatch() for Error Recovery”?
Catch and handle errors, warnings, and messages with tryCatch(). You practise R Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start R Academy?
No prior experience is required. R Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “tryCatch() for Error Recovery” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this R Academy lesson?
Yes. Every R Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.