0

I've tried multiple examples I found on here and elsewhere but it always fails to do what I want.

My R script is simply a configuration validation script, it checks to make sure the user has their environment setup correctly. So I want to try 5 different steps and report on the status of each so that the user can go and fix everything all at once. For example, my first step tests the connection to the database, if that fails I want to print a message and continue on to step 2. But it always halts execution when it errors out and so I only get to the failure and then no more.

I am running the script from command line using RScript.exe on W64. Here's my basic tryCatch, I tried it with the error function and without, it makes no difference, it always breaks on the error.

tryCatch(
    expr = {
       res<- dbGetQuery(con, sql)
       print("SQL query results:")
       print(res)
    }
)
snappymcsnap
  • 2,050
  • 2
  • 29
  • 53
  • 1
    `tryCatch(..., error = function(e) NULL)` will ignore the error and return `NULL` instead. Without `error=...`, `tryCatch` is not catching anything. – r2evans Aug 17 '20 at 20:35

2 Answers2

2

tryCatch catches nothing until you tell it what you want to catch. For instance,

tryCatch(
    expr = {
       res<- dbGetQuery(con, sql)
       print("SQL query results:")
       print(res)
    },
    error = function(e) NULL
)

will return NULL when there's an error. Without that line, it is catching nothing.

Side note: res's existence is not certain. Two scenarios:

  1. res is never defined before now. If there's an error, res will not exist, and any code that follows it will fail with Error: object 'res' not found.

  2. res was defined in a previous code block and is now likely unnecessary. However, if dbGetQuery fails then res will not have been redefined, so it is still present but not related to this query.

Both situations are problematic. I recommend something like:

res <- NULL
res <- tryCatch({
  dbGetQuery(con, sql)
}, error = function(e) conditionMessage(e))
if (is.null(res)) {
  print(paste("oops!", res))
} else {
  print(res)
}
r2evans
  • 141,215
  • 6
  • 77
  • 149
  • 1
    Thanks, that helped me track down the error. The reason it wasn't working for me was that the 'con' variable is the connection, it looks like all it does is configure the properties for the conn string and that nothing should happen until you call dbGetQuery but the creation of con actually establishes the connection to the db, so it was failing on that previous step where I did NOT have the tryCatch! – snappymcsnap Aug 18 '20 at 12:25
1

You're simply not handling your error when it occurs. Here's a reprex to show how to catch an error when it occurs:

function_that_always_fails <- function() stop("I failed")

exception_catcher <- function(e) "Carry on regardless"

tryCatch(expr  = function_that_always_fails())
#> Error in function_that_always_fails(): I failed

tryCatch(expr  = function_that_always_fails(),
         error = exception_catcher)
#> [1] "Carry on regardless"

Or, if you wanted to run a bunch of tests in sequence like in your example, you could have something like:

function_that_sometimes_fails <- function(x)
{
  if(x %% 2 == 0) stop("function ", x, " failed")
  print(paste("test", x, "passed"))
}

exception_catcher <- function(e) print(paste(e$message, "but never mind"))

do_tests <- function() {
  for(i in 1:5)
    tryCatch(expr  = function_that_sometimes_fails(i),
         error = exception_catcher)
}

do_tests()
#> [1] "test 1 passed"
#> [1] "function 2 failed but never mind"
#> [1] "test 3 passed"
#> [1] "function 4 failed but never mind"
#> [1] "test 5 passed"

Created on 2020-08-17 by the reprex package (v0.3.0)

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87