Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the last error

I can get the last calculated value using .Last.value

2 + 2
## [1] 4
.Last.value
## [1] 4

I can access the latest warnings using last.warning.

warning("!!!")
## Warning message:
## !!! 
last.warning
## $`!!!`
##  NULL

I can get the text of the latest error message using geterrmessage()

stop("!!!")
## Error: !!!
geterrmessage()
## [1] "Error: !!!\n"

If I know in advance that an error might be thrown I can use tryCatch to return the error object.

tryCatch(stop("!!!"), error = identity)
## <simpleError in doTryCatch(return(expr), name, parentenv, handler): !!!>

How can I retrieve the last error as an object, after it has been thrown?

For example, if I type

stop("!!!")

Then I want to be able to type getlasterror() or similar and retrieve a simpleError object.

like image 332
Richie Cotton Avatar asked May 01 '16 11:05

Richie Cotton


People also ask

What is last-error?

When an error occurs, most system functions return an error code, usually 0, NULL, or –1. Many system functions also set an additional error code called the last-error code. This error code is maintained separately for each running thread; an error in one thread does not overwrite the last-error code in another thread.

What is an error 2?

You may notice Error:2 on your player from time to time if you've had a live stream or video running for a long time. It may be that your network/internet connection was briefly interrupted. First, try to refresh the page in your browser. This will usually solve the problem.

What is Hresult error?

The 32bits in an HRESULT error code have meanings, allowing the reader to gain additional insights into the error. Of note: The 32nd bit (the top bit) indicates if an error occurred or not. This is why errors are 0x8xxxxxxx.


1 Answers

The modern way

In cases where you are the author of the code, the modern way to solve this is to use the rlang package. You throw errors using abort(), then retrieve the last error with last_error().

library(rlang)
f <- function() {
  abort("@@@")
}
f()
## Error: @@@
last_error()
## <error>
## message: @@@
## class:   `rlang_error`
## backtrace:
##  ─base::withCallingHandlers(...)
##  ─global::f()
## Call `summary(rlang::last_error())` to see the full backtrace
g <- function() {
  msg <- "###"
  abort(msg)
}
g()
## Error: ###
last_error()
## <error>
## message: ###
## class:   `rlang_error`
## backtrace:
##  ─base::withCallingHandlers(...)
##  ─global::g()
## Call `summary(rlang::last_error())` to see the full backtrace
h <- function() {
  err_fn <- abort
  err_fn("$$$")
}
h()
## Error: $$$
last_error()
## <error>
## message: $$$
## class:   `rlang_error`
## backtrace:
##  ─base::withCallingHandlers(...)
##  ─global::h()
## Call `summary(rlang::last_error())` to see the full backtrace

The limitation of this is that it doesn't work with errors generated by stop().


The original answer

Based upon David Arenburg's comment, you can use tryCatch() in conjunction with the traceback.

get_last_error <- function()
{
  tr <- .traceback()
  if(length(tr) == 0)
  {
    return(NULL)
  }
  tryCatch(eval(parse(text = tr[[1]])), error = identity)
}

Examples:

# before an error is thrown
get_last_error()
## NULL

# after an error at the top level
stop("!!!")
## Error: !!!
get_last_error()
## <simpleError in eval(expr, envir, enclos): !!!>

# after an error inside a function
f <- function() stop("@@@")
f()
## Error in f() : @@@
get_last_error()
## <simpleError in eval(expr, envir, enclos): @@@>

A limitation:

When you re-evaluate the error code, all the variables need to be available. So the following examples don't work, for example:

g <- function()
{
  msg <- "###"
  stop(msg)
}

g()
## Error in g() : ###
get_last_error()
## <simpleError in stop(msg): object 'msg' not found>

h <- function()
{
  err_fn <- stop
  err_fn("$$$")
}

h()
## Error in h() : $$$
get_last_error()
## <simpleError in eval(expr, envir, enclos): could not find function "err_fn">

By setting options(error = dump.frames), the call stack at the time of an error is stored in a variable named last.dump in the global environment. The environment last.dump[length(last.dump)] sometimes contains the error object, and sometimes contains the arguments that would create the error.

debugger(last.dump) allows interactive post-mortem exploration of the stack, as an alternative to having the error object.

like image 136
4 revs Avatar answered Oct 12 '22 11:10

4 revs