Skip to content

Clarify try_fetch() and restarts #1850

@lgaborini

Description

@lgaborini

Hi all,
I was exploring some advanced condition handling with {rlang} via try_fetch() to replace some base code.
I am able to establish and call restarts inside try_fetch(), but I was wondering whether this is intentional or not.
The documentation for try_fetch() never mentions restarts or muffling, not even once.
(I guess so since it's a wrapper around withCallingHandlers().)

Micro reprex (this is intentional):

x <- rlang::try_fetch(
   {
      y <- withRestarts(
         {
            rlang::abort("Classed error", class = "custom_error")
            message("Continuing after throw")
            "withRestart return value"
         },
         my_restart = function() {
            message("Handled the error with a restart.")
            "restart return value"
            # rlang::zap() 
         }
      )
      message("Still in try_fetch(): y: ", y)
      y
   },
   custom_error = function(cnd) {
      message("Caught custom_error condition.")
      invokeRestart("my_restart")
   },
   error = function(cnd) {
      message("Caught generic error condition.")
      NULL
   }
)
#> Caught custom_error condition.
#> Handled the error with a restart.
#> Still in try_fetch(): y: restart return value
message("Final value of x: ", x)
#> Final value of x: restart return value

Created on 2025-10-28 with reprex v2.1.1

Also, zap() correctly makes custom_error bubble up to error if return by try_fetch() handlers, but not from the restarts.
I guess it's intentional:

x <- rlang::try_fetch(
   {
      y <- withRestarts(
         {
            rlang::abort("Classed error", class = "custom_error")
            message("Continuing after throw")
            "withRestart return value"
         },
         my_restart = function() {
            message("Handled the error with a restart.")
            rlang::zap()
         }
      )
      message("Still in try_fetch(): y: ", y)
      y
   },
   custom_error = function(cnd) {
      message("Caught custom_error condition.")
      invokeRestart("my_restart")
      # rlang::zap()         # invokes the generic error handler
   },
   error = function(cnd) {
      message("Caught generic error condition.")
      NULL
   }
)
#> Caught custom_error condition.
#> Handled the error with a restart.
#> Still in try_fetch(): y:
message("Final value of x: ", x)
#> Final value of x:

Created on 2025-10-28 with reprex v2.1.1

Thanks!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions