0

My R code is as follows

errors = 0

for(i in c(1:100)){

 tryCatch(expr = {
    API Call
  }, error = {errors=errors+1}, finally = {})

  further code
}

The code is meant to continue execution even if the API call fails and count the number of times error occurred. But I see that if for an iteration there is an error in API call, the code is not executed for further iterations. If I use try(), then I wont be able to count the number of errors.

James Z
  • 12,209
  • 10
  • 24
  • 44

2 Answers2

3

The error= argument of tryCatch should be a function. If you pre-instantiate errors <- 0 before the for loop, there are a couple of options:

My preferred is to catch and check to see if it inherits "error":

errors <- 0L
for (...) {
  res <- tryCatch({
    ...API call...
  },
    error = function(e) e)
  if (inherits(res, "error")) {
    errors <- errors + 1L
  } else {
    something else here
  }
}

Equivalently with try:

errors <- 0L
for (...) {
  res <- try({
    ...API call...
  }, silent = TRUE)
  if (inherits(res, "try-error")) {
    errors <- errors + 1L
  } else {
    something else here
  }
}

Though the reasons I prefer that may be mostly subjective. Another way would be more internal:

errors <- 0L
for (...) {
  res <- tryCatch({
    ...API call...
  },
    error = function(e) { errors <<- errors + 1L; })
  something else here
}
r2evans
  • 141,215
  • 6
  • 77
  • 149
  • The main problem is that after running the tryCatch block, the code does not execute further. The code just stops with an error. – Siddharth Somani Aug 08 '23 at 19:55
  • When your code unmodified, that makes sense: you are not setting `error=` correctly. Compare `tryCatch(stop("hello"), error=function(e)e);message("hello again")` (correct behavior) with `tryCatch(stop("hello"), error={1+1});message("hello again")` – r2evans Aug 08 '23 at 20:25
  • BTW, I would guess that you might need to shift to something like my first code block, checking `inherits(res, "error")`, because it seems likely that your "further code" relies on something being returned from that api call. – r2evans Aug 08 '23 at 20:47
  • However, you've only said that your code stops with an error. Are you certain that the error is due to the API call, or is it from the follow-on code? Is it a presumption in the follow-on code that fails because the api call didn't succeed? Is it unrelated, just happens to be outside of the `tryCatch` expression (but still within the `for` loop)? There's a lot of ambiguity here, not much to work on ... – r2evans Aug 08 '23 at 20:48
  • I don't understand the first code block. Why are you not using `try` there? If you want to store the errors, you shouldn't overwrite `res` in each iteration. – Roland Aug 09 '23 at 05:55
  • @Roland, besides the extra characters and needing to check against `"try-error"` instead of `"error"`, is there an advantage to using `try` over `tryCatch`? I don't try to store the errors themselves, and it was not suggested (afaict) in the OP. – r2evans Aug 09 '23 at 11:51
  • 1
    Clarity of code and a tiny bit of performance ... – Roland Aug 09 '23 at 12:07
0

# set up scenario
api_call <- function(in_1){
  if(in_1 %in% c(5,7)){
    stop("bad num")
  }
  in_1+.5
}

for(i in 1:10){
  print(api_call(i))
}

# wrap it up
library(purrr)
safe_api_call <- safely(api_call)
for(i in 1:10){
  print(safe_api_call(i)$result)
}

# add counting of errors

error_count <- 0
for(i in 1:10){
  r <- safe_api_call(i)
  print(r$result)
  error_count <- error_count + inherits(r$error,"error")
}
error_count
Nir Graham
  • 2,567
  • 2
  • 6
  • 10