Save traceback on error using tryCatch
Asked Answered
E

3

5

When calling an R function inside my webapp, I would like to catch the stack-trace when an error occurs and present it to the user for debugging purposes. Something like the output of traceback() in an interactive session. However, traceback doesn't seem to work when it is called inside the error handler, it returns No traceback available:

f <- function() {
    g <- function() stop("test traceback")
    g()
}

errhandler <- function(e){
  stacktrace <- traceback()
  unlist(stacktrace);
}

out <- tryCatch(f(), error=errhandler) 

Is there any way I can programatically catch the stack trace of an error? I.e. get the output that I would get when calling traceback() manually after the error:

f()
traceback()
Eutherian answered 2/6, 2013 at 4:37 Comment(0)
E
4

It turns out that the latest version of the evaluate package has a function called try_capture_stack which is a pretty good implementation of this.

Eutherian answered 2/6, 2013 at 23:50 Comment(1)
What are the bad side-effects of using .try_quietly?Anomalous
S
2

The function tools:::.try_quietly does something similar:

f <- function() {
  g <- function() stop("test traceback")
  g()
}

tools:::.try_quietly(f()) 

Error: test traceback
Call sequence:
3: stop("test traceback")
2: g()
1: f()

However, the errors and warnings are printed to outConn using sink() - this means you can't directly assign the results to an object. To work around this, you may have to change the code to use print() instead of sink (untried).

Scot answered 2/6, 2013 at 6:0 Comment(1)
I found this one as well, but it has many nasty side effects and doesn't play nice with tryCatch, etc.Eutherian
P
1

I did not get a stack as with traceback with try_capture_stack, so I wrote a solution that works like try, except that it also returns the call stack. tools:::.try_quietly is neat, but does not save the stacks for later inspection...

tryStack <- function(
expr,
silent=FALSE
)
{
tryenv <- new.env()
out <- try(withCallingHandlers(expr, error=function(e)
  {
  stack <- sys.calls()
  stack <- stack[-(2:7)]
  stack <- head(stack, -2)
  stack <- sapply(stack, deparse)
  if(!silent && isTRUE(getOption("show.error.messages"))) 
    cat("This is the error stack: ", stack, sep="\n")
  assign("stackmsg", value=paste(stack,collapse="\n"), envir=tryenv)
  }), silent=silent)
if(inherits(out, "try-error")) out[2] <- tryenv$stackmsg
out
}

lower <- function(a) a+10
upper <- function(b) {plot(b, main=b) ; lower(b) }

d <- tryStack(upper(4))
d <- tryStack(upper("4"))
cat(d[2])

More info in my answer here: https://mcmap.net/q/505703/-get-stack-trace-on-trycatch-39-ed-error-in-r

Pectize answered 30/11, 2016 at 23:2 Comment(1)
Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer to this specific question here, and provide the link for reference. This also goes for the other answers you have added recently.Publea

© 2022 - 2024 — McMap. All rights reserved.