0Pricing
R Academy · Lesson

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 with warning = function(w) {...}
  • The handler's return value becomes the result of tryCatch()
  • finally always executes — ideal for cleanup
  • Wrap loop bodies in tryCatch() for robust iteration over unreliable inputs
  • e$message or conditionMessage(e) extracts the error text
  • try(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.

All lessons in this course

  1. Errors, Warnings, and Messages in R
  2. tryCatch() for Error Recovery
  3. withCallingHandlers() and Restarts
  4. Writing Robust Functions with stop() and warning()
← Back to R Academy