How does error management work in callr package?

79 views Asked by At

I'm trying to figure out how to use the error handling in the callr package (which creates sub processes for R).

Here is a reprex:

rp <- callr::r_bg(function() stop("You should see this"), error = getOption("callr.error", "error"))
Sys.sleep(2)
rp$get_result()
#> Error: ! in callr subprocess.
#> Caused by error in `(function () …`:
#> ! You should see this

Created on 2023-07-11 with reprex v2.0.2

What I want to accomplish is to suppress the messages #> Error: ! in callr subprocess. #> Caused by error in (function () …: and only show Error: You should see this. The background is that this will go into a function and I think it will confuse users to see the callr reference.

It seems that the error argument could be used to accomplish that. The documentation reads:

error: What to do if the remote process throws an error. See details below.

But I can't find these details and don't know what options might be valid here.

1

There are 1 answers

0
JBGruber On

I finally found this in the documentation of r_bg:

#' @inheritParams r

Which indicates that the answer to my question is in the help file of the function callr::r:

Error handling

callr handles errors properly. If the child process throws an error, then callr throws an error with the same error message in the main process.

The error expert argument may be used to specify a different behavior on error. The following values are possible:

  • error is the default behavior: throw an error in the main process, with a prefix and the same error message as in the subprocess.

  • stack also throws an error in the main process, but the error is of a special kind, class callr_error, and it contains both the original error object, and the call stack of the child, as written out by utils::dump.frames(). This is now deprecated, because the error thrown for "error" has the same information.

  • debugger is similar to stack, but in addition to returning the complete call stack, it also start up a debugger in the child call stack, via utils::debugger().

The default error behavior can be also set using the callr.error option. This is useful to debug code that uses callr.

callr uses parent errors, to keep the stacks of the main process and the subprocess(es) in the same error object.

In other words, the message can not be suppressed at the moment (as far as I can see), except with something hacky like this:

rp <- callr::r_bg(function() stop("You should see this"), error = "error")
Sys.sleep(2)

res <- tryCatch(rp$get_result(), error = function(e) {
  # e <<- e
  e$message <- "my package"
  print(e)
})
#> <callr_error/rlib_error_3_0/rlib_error/error>
#> Error: 
#> ! my package
#> Caused by error in `(function () …`:
#> ! You should see this
#> ---
#> Subprocess backtrace:
#> 1. base::stop("You should see this")
#> 2. | base::.handleSimpleError(function (e) …
#> 3. global h(simpleError(msg, call))