Like any R objects, errors captured with catchers like tryCatch()
have a class() which you can test with inherits(). However,
with chained errors, the class of a captured error might be
different than the error that was originally signalled. Use
cnd_inherits() to detect whether an error or any of its parent
inherits from a class.
Whereas inherits() tells you whether an object is a particular
kind of error, cnd_inherits() answers the question whether an
object is a particular kind of error or has been caused by such an
error.
Some chained conditions carry parents that are not inherited. See
the .inherit argument of abort(), warn(), and inform().
Arguments
- cnd
A condition to test.
- class
A class passed to
inherits().
Capture an error with cnd_inherits()
Error catchers like tryCatch() and try_fetch() can only match
the class of a condition, not the class of its parents. To match a
class across the ancestry of an error, you'll need a bit of
craftiness.
Ancestry matching can't be done with tryCatch() at all so you'll
need to switch to withCallingHandlers(). Alternatively, you can
use the experimental rlang function try_fetch() which is able to
perform the roles of both tryCatch() and withCallingHandlers().
withCallingHandlers()
Unlike tryCatch(), withCallingHandlers() does not capture an
error. If you don't explicitly jump with an error or a value
throw, nothing happens.
Since we don't want to throw an error, we'll throw a value using
callCC():
f <- function() {
parent <- error_cnd("bar", message = "Bar")
abort("Foo", parent = parent)
}
cnd <- callCC(function(throw) {
withCallingHandlers(
f(),
error = function(x) if (cnd_inherits(x, "bar")) throw(x)
)
})
class(cnd)
#> [1] "rlang_error" "error" "condition"
class(cnd$parent)
#> [1] "bar" "rlang_error" "error" "condition"try_fetch()
This pattern is easier with try_fetch(). Like
withCallingHandlers(), it doesn't capture a matching error right
away. Instead, it captures it only if the handler doesn't return a
zap() value.
cnd <- try_fetch(
f(),
error = function(x) if (cnd_inherits(x, "bar")) x else zap()
)
class(cnd)
#> [1] "rlang_error" "error" "condition"
class(cnd$parent)
#> [1] "bar" "rlang_error" "error" "condition"Note that try_fetch() uses cnd_inherits() internally. This
makes it very easy to match a parent condition:
