Get Stack Trace on Trycatch'Ed Error in R

get stack trace on tryCatch'ed error in R

For interactive use one might trace(stop, quote(print(sys.calls()))) to print the call stack at the time stop() is invoked.

From ?tryCatch,

 The function 'tryCatch' evaluates its expression argument in a
context where the handlers provided in the '...' argument are
available.

whereas

 Calling handlers are established by 'withCallingHandlers'...
the handler is called... in the context where the condition
was signaled...

so

>     withCallingHandlers(x(), error=function(e) print(sys.calls()))
[[1]]
withCallingHandlers(x(), error = function(e) print(sys.calls()))

[[2]]
x()

[[3]]
y()

[[4]]
z()

[[5]]
stop("asdf")

[[6]]
.handleSimpleError(function (e)
print(sys.calls()), "asdf", quote(z()))

[[7]]
h(simpleError(msg, call))

Error in z() : asdf

This is thwarted if there is an inner tryCatch

withCallingHandlers({
tryCatch(x(), error=function(e) stop("oops"))
}, error=function(e) print(sys.calls()))

as we only have access to the call stack after the tryCatch has 'handled' the error.

Save traceback on error using tryCatch

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.

Printing stack trace and continuing after error occurs in R

I ended up writing a general-purpose logger that produces Java-like logging messages when the standard R "message", "warning" and "stop" methods are called. It includes timestamps, and stack traces for warnings and above.

Many thanks to Man Group for permission to distribute this! Thanks also to Bob Albright, whose answer gave me a leg-up to what I was looking for.

withJavaLogging = function(expr, silentSuccess=FALSE, stopIsFatal=TRUE) {
hasFailed = FALSE
messages = list()
warnings = list()
logger = function(obj) {
# Change behaviour based on type of message
level = sapply(class(obj), switch, debug="DEBUG", message="INFO", warning="WARN", caughtError = "ERROR",
error=if (stopIsFatal) "FATAL" else "ERROR", "")
level = c(level[level != ""], "ERROR")[1]
simpleMessage = switch(level, DEBUG=,INFO=TRUE, FALSE)
quashable = switch(level, DEBUG=,INFO=,WARN=TRUE, FALSE)

# Format message
time = format(Sys.time(), "%Y-%m-%d %H:%M:%OS3")
txt = conditionMessage(obj)
if (!simpleMessage) txt = paste(txt, "\n", sep="")
msg = paste(time, level, txt, sep=" ")
calls = sys.calls()
calls = calls[1:length(calls)-1]
trace = limitedLabels(c(calls, attr(obj, "calls")))
if (!simpleMessage && length(trace) > 0) {
trace = trace[length(trace):1]
msg = paste(msg, " ", paste("at", trace, collapse="\n "), "\n", sep="")
}

# Output message
if (silentSuccess && !hasFailed && quashable) {
messages <<- append(messages, msg)
if (level == "WARN") warnings <<- append(warnings, msg)
} else {
if (silentSuccess && !hasFailed) {
cat(paste(messages, collapse=""))
hasFailed <<- TRUE
}
cat(msg)
}

# Muffle any redundant output of the same message
optionalRestart = function(r) { res = findRestart(r); if (!is.null(res)) invokeRestart(res) }
optionalRestart("muffleMessage")
optionalRestart("muffleWarning")
}
vexpr = withCallingHandlers(withVisible(expr),
debug=logger, message=logger, warning=logger, caughtError=logger, error=logger)
if (silentSuccess && !hasFailed) {
cat(paste(warnings, collapse=""))
}
if (vexpr$visible) vexpr$value else invisible(vexpr$value)
}

To use it, just wrap it around your code:

withJavaLogging({
// Your code here...
})

For a quieter output in the absence of errors (useful for tests!), set the silentSuccess flag. Messages will only be output if an error occurs, to give context to the failure.

To achieve the original goal (dump stack trace + carry on), just use try:

try(withJavaLogging({
// Your code here...
}, stopIsFatal=FALSE))

How to trace an error most likely due to server call?

I think this is due to requests coming faster than OSRM can handle them. This leads to a full OSRM request-queue and at last to spooky error messages. See here for a partial explanation.

Using the latest OSRMR release from github you should not get this kind of error anymore. In v0.1.31 I changed the viaroute function of OSRMR package to account for this by adding a new optional parameter timeout. timeout puts the viaroute call to sleep for 1 ms by default. The timeout can also be adjusted.

You can install the latest OSRMR release from github with:

devtools::install_github("ims-fhs/osrmr")

The following reproducible example works for me:

osrmr::run_server("switzerland-latest", "C:/OSRM_API5")

n <- 1e3
locs <- data.frame(x = c(47.424536, 47.427061),
y = c(9.365103, 9.365062), stringsAsFactors = FALSE)

for (i in 1:n) {
print(i)
for (j in 1:n) {
osrmr::viaroute(locs$x[1], locs$y[1], locs$x[2], locs$y[2], instructions = FALSE, api_version = 5, localhost = TRUE, timeout = 0.001)
}
}
osrmr::quit_server()

Tracking which group fails in a dplyr chain

A full example of using purrr::safely:

Prep

library(tidyverse)
data(iris)
iris$Petal.Width[iris$Species == "versicolor"] <- NA

Safely run the models

If you're uninterested in the actual error (i.e. that the cause was 0 (non-NA) cases), you can do:

iris %>%
group_by(Species) %>%
do(mod = safely(lm)(Petal.Length ~ Petal.Width, data = .)$result) %>%
mutate(Slope = ifelse(!is.null(mod), summary(mod)$coeff[2], NA))

And we're done!

Source: local data frame [3 x 3]
Groups: <by row>

# A tibble: 3 × 3
Species mod Slope
<fctr> <list> <dbl>
1 setosa <S3: lm> 0.5464903
2 versicolor <NULL> NA
3 virginica <S3: lm> 0.6472593

We can clearly see which group failed (because it has NULL instead of a model, and it's Slope is unknown). Moreover, we still obtained the correct models and slopes for the other groups, so we haven't wasted computation time (this can be quite nice when running complex models on larger datasets).

Keeping track of both the models and the errors

step1 <- iris %>%
group_by(Species) %>%
do(res = safely(lm)(Petal.Length ~ Petal.Width, data = .)) %>%
mutate(err = map(list(res), 'error'),
mod = map(list(res), 'result'))

Unfortunately, we have to use extra list calls there, not entirely sure why. Alternatively, you can ungroup first.

To see which (if any) groups have error-ed, we can use:

filter(step1, !is.null(err))

To rescue the result of the non-errored groups simply filter first:

step1 %>% 
filter(is.null(err)) %>%
mutate(Slope = summary(mod)$coeff[2])

You could also look into the broom package if want to obtain the coefficients of models within tidy chains.

Error when i added new user ACLPOLICY :ERROR StackTrace --- [tp1969073751-39] Full Stack Trace: Error

The ACL is wrong, seems edited, in application scope you're using My Project instead of MyProject, I modified it and works well:

description: project level ACL.
context:
project: 'MyProject'
for:
resource:
- equals:
kind: event
allow: [read]
job:
- allow: [run, read]
adhoc:
- deny: run
node:
- allow: [read, run]
by:
group: demo

---

# Application scope
description: application level ACL.
context:
application: 'rundeck'
for:
project:
- match:
name: 'MyProject'
allow: [read]
by:
group: demo


Related Topics



Leave a reply



Submit