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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions