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
Converting Date to a Day of Week in R
Scoping and Functions in R 2.11.1:What's Going Wrong
Plot Decision Boundaries with Ggplot2
Splitting Columns by Number of Characters
How to Remove All Rows from a Data.Frame
A^K for Matrix Multiplication in R
How to Remove Specific Special Characters in R
Retrieve Census Tract from Coordinates
Get the Last Row of a Previous Group in Data.Table
R: Split Elements of a List into Sublists
How to Show Corpus Text in R Tm Package
How to Rotate the X-Axis Labels 90 Degrees in Levelplot
Grid.Arrange Using List of Plots
Ggplot2 Multiline Title, Different Indentations
Faster Way to Find the First True Value in a Vector
Set Upper Limit in Ggplot to Include Label Greater Than the Maximum Value