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.

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"