Recursively calling a function until the error is no longer an error at run time, i think i get the error because of a stack overflow,I have tried but not succeed end with NULL or error,any help,thanks.
fetchData <- function()
{
#withRestarts(invokeRestart("a"),a=function(){QueryTrueFX()}) #i have tried restart within error function though i get NULL only
qtf <- tryCatch(QueryTrueFX(),warning = function(w) {},error = function(e) {QueryTrueFX()})
if(is.null(qtf))
{
fetchData()
}
}
a<-fetchData()
Error in file(con, "r") : all connections are in use
Called from: eval(expr, envir, enclos)
Error during wrapup: all connections are in use
Error during wrapup: target context is not on the stack
a=tryCatch(fetchData(), error=function(e) NULL )
a
NULL
Related
I have code that includes several initial checks of different parameter values. The code is part of a larger project involving several R scripts as well as calls from other environments. If a parameter value does not pass one of the checks, I want to
Generate a customizable result code
Skip the remaining code (which is not going to work anyhow if the parameters are wrong)
Create a log entry with the line where the error was thrown (which tells me which test was not passed by the parameters)
Print my customizable result code to the console (without a more detailed explanation / trace back from the error)
Otherwise, the remaining code should be run. If there are other errors (not thrown by me), I also need an error handling resulting in a customizable general result code (signalling that there was an error, but that it was not one thrown by me) and a more detailled log.
The result codes are part of the communication with a larger environment and just distinguishes between wrong parameter values (i.e., errors thrown by me) and other internal problems (that might occur later in the script).
I would like to use tryCatchLog because it allows me to log a detailed traceback including the script name (I am sourcing my own code) and the line number. I have not figured out, however, how to generate my own error code (currently I am doing this via the base function stop()) and pass this along using tryCatchLog (while also writing a log).
Example
In the following example, my parameter_check() throws an error via stop() with my result code "400". Using tryCatchLog I can catch the error and get a detailed error message including a traceback. However, I want to seperate my own error code (just "400"), which should be printed to the console, and a more detailed error message, which should go to a log file.
library(tryCatchLog)
parameter_check <- function(error) {
if (error){
stop("400")
print("This line should not appear")
}
}
print("Beginning")
tryCatchLog(parameter_check(error = TRUE),
error = function(e) {print(e)}
)
print("End")
Currently, the result is:
[1] "Beginn"
ERROR [2021-12-08 11:43:38] 400
Compact call stack:
1 tryCatchLog(parameter_check(0), error = function(e) {
2 #3: stop("400")
Full call stack:
1 tryCatchLog(parameter_check(0), error = function(e) {
print(e)
2 tryCatch(withCallingHandlers(expr, condition =
cond.handler), ..., finall
3 tryCatchList(expr, classes, parentenv, handlers)
4 tryCatchOne(expr, names, parentenv, handlers[[1]])
5 doTryCatch(return(expr), name, parentenv, handler)
6 withCallingHandlers(expr, condition = cond.handler)
7 parameter_check(0)
8 #3: stop("400")
9 .handleSimpleError(function (c)
{
if (inherits(c, "condition")
<simpleError in parameter_check(0): 400>
I would like to get my own result code ("400") so that I can print it to the console while logging the complete error message in a file. Is there a way of doing it without writing code parsing the error message, etc.?
Solution with tryCatch
Based on the hint by R Yoda and this answers this is a solution with tryCatch and calling handlers.
### Parameters
log_file_location <- "./logs/log.txt"
### Defining functions
parameter_check_1 <- function(error) {
if (error){
stop("400")
}
}
parameter_check_2 <- function(error) {
if (error){
stop("400")
}
}
write_to_log <- function(file_location, message) {
if (file.exists(file_location))
{write(message, file_location, append = TRUE)}
else
{write(message, file_location, append = FALSE)}
}
parameter_check <- function(){
print("Beginning of parameter check")
print("First check")
parameter_check_1(error = TRUE)
print("Second check")
parameter_check_2(error = FALSE)
print("End of parameter check")
}
main<- function() {
print("Beginning of main function")
log(-1) # throws warning
log("error") # throws error
print("End of main function")
}
### Setting parameters
result_code_no_error <- "200"
result_code_bad_request <- "400"
result_code_internal_error <- "500"
# initial value for result_code
result_code <- result_code_no_error
print("Beginning of program")
### Execute parameter check with tryCatch and calling handlers
# Error in parameter checking functions should result in result_code_bad_request
tryCatch(withCallingHandlers(parameter_check(),
error = function(condition){},
warning = function(condition){
write_to_log(log_file_location, condition$message)
invokeRestart("muffleWarning")
}
),
error = function(condition) {
write_to_log(log_file_location, condition$message)
result_code <<- result_code_bad_request
}
)
### Execute main section with tryCatch and calling handlers
# Error in main section should result in result_code_internal_error
# main section should only be excecuted if there is no error (internal or bad request) in the previous section
if (result_code == result_code_no_error) {
tryCatch(withCallingHandlers(main(),
error = function(condition){},
warning = function(condition){
write_to_log(log_file_location, condition$message)
invokeRestart("muffleWarning")
}
),
error = function(condition) {
write_to_log(log_file_location, condition$message)
result_code <<- result_code_internal_error
}
)
}
print("End of program")
print(result_code)
As explained in the vignette for tryCatchLog this has the disadvantage of not logging the precise location of the error. I am not passing on the error message from stop("400"), because all parameter checking functions are in one function call now, but this could be done using condition$message.
The solution is (totally independent of using tryCatchLog or standard R tryCatch):
...
error = function(e) {print(e$message)}
..
Background (how R errors work): They create an object of type (error) condition:
e <- simpleError("400") # same "condition" object as created by stop("400")
str(e)
# List of 2
# $ message: chr "400"
# $ call : NULL
# - attr(*, "class")= chr [1:3] "simpleError" "error" "condition"
print(e$message)
[1] "400"
When I execute:
my_env <- new.env(parent = emptyenv())
test <- purrr::safely(get("meta", envir = my_env))
I get the following error:
Error in get("meta") : object 'meta' not found
The error is correct in the sense of that the meta variable is not defined in the environment but my line of thinking was that safely would return a NULL in that case.
I can get around the error by using checking using exists first but I was curious about why safely fails. Am I wrong in thinking of safely as the equivalent of a try-catch?
You are misinterpreting the actions of the safely function. It was actually succeeding. If you had examined the value of test, you should have seen:
> test
[1] "Error in get(\"meta\", env = my_env) : object 'meta' not found\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in get("meta", env = my_env): object 'meta' not found
To suppress error messages from being visible at the console you can either turn off reporting with options(show.error.messages = FALSE) or you can redirect the destination of stderr().
i'm trying to run a API request for a number of parameters with the lapply function in R.
However, when i run this function, i get the error " Error in file(con, "r") : cannot open the connection"
Google suggests using setInternet2(TRUE) to fix this issue, however, i get the error: Error: 'setInternet2' is defunct.
See help("Defunct"
localisedDestinationNameForGivenLang <- function (LocationId) {
gaiaURL <- paste0("https://URL/",LocationId, "?geoVersion=rwg&lcid=", "1036",
"&cid=geo&apk=explorer")
print(LocationId)
localisation <- fromJSON(gaiaURL)
}
lapply(uniqueLocationId, localisedDestinationNameForGivenLang)
Can someone suggest a fix please?
Here's a sample of how you could identify which sites are throwing errors while still getting response from the ones that don't:
urls = c("http://citibikenyc.com/stations/test", "http://citibikenyc.com/stations/json")
grab_data <- function(url) {
out <- tryCatch(
{fromJSON(url)},
error=function(x) {
message(paste(url, x))
error_msg = paste(url, "threw an error")
return(error_msg)
})
return(out)
}
result <- lapply(urls, grab_data)
result will be a list that contains API response for urls that work, and error msg for those that don't.
I'll catch an error using tryCatch, and attempt to handle the error. However, how can I rethrow the error if I cannot handle the error locally (i.e. delegate to error handlers of parent functions higher up in the call stack)?
I tried using signalCondition but instead of seeing the rethrown error, all I see is NULL:
> error.can.be.handled <- function(e) F
>
> foo <- function() stop("foo stop!")
> tryCatch(foo(),
+ error = function(e) {
+ if (error.can.be.handled(e)) {
+ # handle error
+ }
+ else
+ signalCondition(e) # Rethrow error
+ }
+ )
NULL # I expected to see 'Error in foo() : foo stop!' here
What's going wrong?
tryCatch(stop("oops"), error=function(e) stop(e))
will re-signal the stop condition, although the context has been lost
> tryCatch(stop("oops"), error=function(e) stop(e))
Error in doTryCatch(return(expr), name, parentenv, handler) : oops
> traceback()
5: stop(e)
4: value[[3L]](cond)
3: tryCatchOne(expr, names, parentenv, handlers[[1L]])
2: tryCatchList(expr, classes, parentenv, handlers)
1: tryCatch(stop("oops"), error = function(e) stop(e))
> tryCatch(stop("oops"))
Error in tryCatchList(expr, classes, parentenv, handlers) : oops
> traceback()
3: stop("oops")
2: tryCatchList(expr, classes, parentenv, handlers)
1: tryCatch(stop("oops"))
Returning just e as #tonytonov suggests does signal that a condition has occurred, but not that an error has occurred.
There's a workaround you can use to avoid having to catch and re-throw the error at all. Basically, use a success flag with an on.exit handler to run a block of code only if the code in question fails:
foo <- function() stop("foo stop!")
runFoo <- function() {
success <- FALSE
on.exit({
if (!success) {
## Handle failure
}
})
result <- foo()
success <- TRUE
result
}
runFoo()
The main disadvantage of this approach is that while you know an error occurred (because success never got set to TRUE), you don't get access to the error object itself, so you will need to use some other method to detect whether you can handle the error or not.
The runFoo wrapper function is needed because the on.exit expression runs when exiting the current function, so it needs to be run inside a function. If the code that you're writing is already inside a function, then you don't need to use this wrapper.
There is no need in signalCondition() whatsoever:
tryCatch(foo(),
error = function(e) {
if (error.can.be.handled(e)) {
# handle error
}
else
e # Rethrow error
}
)
<simpleError in foo(): foo stop!>
Problem
It seems that within a function, when you evaluate an expression that yields an error more than once, you get the warning restarting interrupted promise evaluation. For instance:
foo <- function() stop("Foo error")
bar <- function(x) {
try(x)
x
}
bar(foo())
yields
Error in foo() : Foo error
Error in foo() : Foo error
In addition: Warning message:
In bar(foo()) : restarting interrupted promise evaluation
How to avoid this warning and deal with it properly?
Background
Especially with operations like writing to a database, you might encounter locking errors that require you to retry your operation a few times. Hence I'm creating a wrapper around tryCatch that re-evaluates an expression up to n times until successful:
tryAgain <- function(expr, n = 3) {
success <- T
for (i in 1:n) {
res <- tryCatch(expr,
error = function(e) {
print(sprintf("Log error to file: %s", conditionMessage(e)))
success <<- F
e
}
)
if (success) break
}
res
}
However, I'm getting loads of restarting interrupted promise evaluation messages:
> tryAgain(foo())
[1] "Log error to file: Foo error"
[1] "Log error to file: Foo error"
[1] "Log error to file: Foo error"
<simpleError in foo(): Foo error>
Warning messages:
1: In doTryCatch(return(expr), name, parentenv, handler) :
restarting interrupted promise evaluation
2: In doTryCatch(return(expr), name, parentenv, handler) :
restarting interrupted promise evaluation
Ideally I want to avoid these messages altogether rather than just muffle them, since I might also want to handle genuine warnings coming from expr.
You can also try this without silent=TRUE if you want each error message to show. In neither case will you get the message about promises:
foo <- function() stop("Foo error")
bar <- function(x) {
try(eval.parent(substitute(x)), silent = TRUE)
x
}
bar(foo())