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

## Usage

cnd_inherits(cnd, class)

## 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:

cnd <- try_fetch(
f(),
bar = function(x) x
)

# This is the parent
class(cnd)
#> [1] "bar"         "rlang_error" "error"       "condition"