2

calling source() for non-existing file generates both error and warning:

source('nofile.R')
# Error in file(filename, "r", encoding = encoding) : 
#   cannot open the connection
# In addition: Warning message:
#   In file(filename, "r", encoding = encoding) :
#   cannot open file 'nofile.R': No such file or directory

I tried to catch the error in tryCatch():

trysource <- function(src.file){
  result <- tryCatch(
    expr    = {source(src.file);},
    error   = function(e){cat('My error: ',   e$message, '\n');},
    finally = cat("finished.\n")
  ); 
}

trysource('nofile.R')
# My error:  cannot open the connection 
# finished.
# Warning message:
#   In file(filename, "r", encoding = encoding) :
#   cannot open file 'nofile.R': No such file or directory

as you see, it catches the error successfully. Then I added warning= part:

trysource <- function(src.file){
  result <- tryCatch(
    expr    = {source(src.file);},
    error   = function(e){cat('My error: ',   e$message, '\n');},
    warning = function(w){cat('My warning: ', w$message, '\n');},
    finally = cat("finished.\n")
  ); 
}

trysource('nofile.R')
# My warning:  cannot open file 'nofile.R': No such file or directory 
# finished.

Now it catches the warning but ignores the error! Can anyone explain why it happens and if there is any way to catch both?

Vasily A
  • 8,256
  • 10
  • 42
  • 76
  • Would it suffice to elevate warnings to errors and run the only-error-catching version? `options(warn=2)` By the way, if this means catch both simultaneously, I doubt you can do that. The warning may be queued and then the error caught; if you make the warning an error, it will be caught before the second error is generated. If seeing all is important, perhaps you could try wrapping your code in nested `tryCatch` blocks, where the inner catches errors and the outer warnings. I'm not sure exactly what you want though. – Philip Jan 15 '16 at 17:32
  • 1
    This question may be helpful: http://stackoverflow.com/questions/19433848/handling-errors-before-warnings-in-trycatch – Matthew Plourde Jan 15 '16 at 17:42
  • When a condition is signaled, the proper handler (if defined) is called. The expression stops its execution. Apparently, `file` generates the warning first. So your `tryCatch` calls the `warning` function and then executes the `finally` part. The error is actually never generated. See `?tryCatch` for more details (not a soft read I should add). – nicola Jan 15 '16 at 17:46
  • Perhaps you need to process the warning event and then allow continuance. – IRTFM Jan 15 '16 at 20:14
  • 1
    thank you all for the comments! now I see there's no easy general solution. I checked the question mentioned by @MatthewPlourde where they suggest custom catch function (`MyLibrary.Sys.Try()`)... In my particular case, I mainly needed to check if the `source()` loading was successful or not, so maybe I should rather work on that specific question only. – Vasily A Jan 15 '16 at 20:28
  • 1
    use `withCallingHandlers(..., warning=function(...) invokeRestart("muffleWarning"))` to handle the warning and invoke the continuation. As the first argument to `withCallingHandlers()`, use `tryCatch(..., error=function(...) {...})` to catch the error and terminate execution. Whatever expressions you're trying to handle are in the first argument to `tryCatch()`. – Martin Morgan Jan 15 '16 at 21:14
  • thanks @MartinMorgan, I will try to implement a solution with `withCallingHandlers`! – Vasily A Jan 15 '16 at 22:38

0 Answers0