Skip to content

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)



A condition to test.


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


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) {
    error = function(x) if (cnd_inherits(x, "bar")) throw(x)

#> [1] "rlang_error" "error"       "condition"
#> [1] "bar"         "rlang_error" "error"       "condition"


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(
  error = function(x) if (cnd_inherits(x, "bar")) x else zap()

#> [1] "rlang_error" "error"       "condition"
#> [1] "bar"         "rlang_error" "error"       "condition"