% Generated by roxygen2: do not edit by hand % Please edit documentation in R/cnd-handlers.R \name{try_fetch} \alias{try_fetch} \title{Try an expression with condition handlers} \usage{ try_fetch(expr, ...) } \arguments{ \item{expr}{An R expression.} \item{...}{<\code{\link[=dyn-dots]{dynamic-dots}}> Named condition handlers. The names specify the condition class for which a handler will be called.} } \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} \code{try_fetch()} establishes handlers for conditions of a given class (\code{"error"}, \code{"warning"}, \code{"message"}, ...). Handlers are functions that take a condition object as argument and are called when the corresponding condition class has been signalled. A condition handler can: \itemize{ \item \strong{Recover from conditions} with a value. In this case the computation of \code{expr} is aborted and the recovery value is returned from \code{try_fetch()}. Error recovery is useful when you don't want errors to abruptly interrupt your program but resume at the catching site instead. \if{html}{\out{
}}\preformatted{# Recover with the value 0 try_fetch(1 + "", error = function(cnd) 0) }\if{html}{\out{
}} \item \strong{Rethrow conditions}, e.g. using \code{abort(msg, parent = cnd)}. See the \code{parent} argument of \code{\link[=abort]{abort()}}. This is typically done to add information to low-level errors about the high-level context in which they occurred. \if{html}{\out{
}}\preformatted{try_fetch(1 + "", error = function(cnd) abort("Failed.", parent = cnd)) }\if{html}{\out{
}} \item \strong{Inspect conditions}, for instance to log data about warnings or errors. In this case, the handler must return the \code{\link[=zap]{zap()}} sentinel to instruct \code{try_fetch()} to ignore (or zap) that particular handler. The next matching handler is called if any, and errors bubble up to the user if no handler remains. \if{html}{\out{
}}\preformatted{log <- NULL try_fetch(1 + "", error = function(cnd) \{ log <<- cnd zap() \}) }\if{html}{\out{
}} } Whereas \code{tryCatch()} catches conditions (discarding any running code along the way) and then calls the handler, \code{try_fetch()} first calls the handler with the condition on top of the currently running code (fetches it where it stands) and then catches the return value. This is a subtle difference that has implications for the debuggability of your functions. See the comparison with \code{tryCatch()} section below. } \section{Stack overflows}{ A stack overflow occurs when a program keeps adding to itself until the stack memory (whose size is very limited unlike heap memory) is exhausted. \if{html}{\out{
}}\preformatted{# A function that calls itself indefinitely causes stack overflows f <- function() f() f() #> Error: C stack usage 9525680 is too close to the limit }\if{html}{\out{
}} Because memory is very limited when these errors happen, it is not possible to call the handlers on the existing program stack. Instead, error conditions are first caught by \code{try_fetch()} and only then error handlers are called. Catching the error interrupts the program up to the \code{try_fetch()} context, which allows R to reclaim stack memory. The practical implication is that error handlers should never assume that the whole call stack is preserved. For instance a \code{\link[=trace_back]{trace_back()}} capture might miss frames. Note that error handlers are only run for stack overflows on R >= 4.2. On older versions of R the handlers are simply not run. This is because these errors do not inherit from the class \code{stackOverflowError} before R 4.2. Consider using \code{\link[=tryCatch]{tryCatch()}} instead with critical error handlers that need to capture all errors on old versions of R. } \section{Comparison with \code{tryCatch()}}{ \code{try_fetch()} generalises \code{tryCatch()} and \code{withCallingHandlers()} in a single function. It reproduces the behaviour of both calling and exiting handlers depending the on the return value of the handler. If the handler returns the \code{\link[=zap]{zap()}} sentinel, it is taken as a calling handler that declines to recover from a condition. Otherwise, it is taken as an exiting handler which returns a value from the catching site. The important difference between \code{tryCatch()} and \code{try_fetch()} is that the program in \code{expr} is still fully running when an error handler is called. Because the call stack is preserved, this makes it possible to capture a full backtrace from within the handler, e.g. when rethrowing the error with \code{abort(parent = cnd)}. Technically, \code{try_fetch()} is more similar to (and implemented on top of) \code{\link[base:conditions]{base::withCallingHandlers()}} than \verb{tryCatch().} }