% 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().}
}