Exception in Shiny apps can crash the app. Most time we don't want the app to crash but just stop this code block, inform users and continue with other code blocks. This function is designed to handle these issues.
shinyCatch(
expr,
position = "bottom-right",
blocking_level = "none",
shiny = TRUE,
prefix = "SPS",
trace_back = spsOption("traceback")
)
expression
client side message bar position, one of: c("top-right", "top-center", "top-left","top-full-width", "bottom-right", "bottom-center", "bottom-left","bottom-full-width").
what level you want to block the execution, one of "error", "warning", "message", default is "none", do not block following code execution.
bool, only show message on console log but not in Shiny app
when it is FALSE
. Useful if you want to keep the exception only to the server
and hide from your users. You do not need to set it to FALSE
when purely work
outside shiny, it will automatically detect if you are working in a Shiny
environment or not.
character, what prefix to display on console for the log, e.g.
for error, the default will be displayed as "SPS-ERROR". You can make your own
prefix, like prefix = "MY"
, then, it will be "MY-ERROR". Use ""
if you do not
want any prefix, like prefix = ""
, then, it will just be "ERROR".
multiple levels
bool, added since spsComps 0.2, if the expression is blocked
or has errors, cat the full trace back? It will display called functions
and code source file and line number if possible. Default follows the
SPS spsOption("traceback")
setting. You can set it by running spsOption("traceback", TRUE)
.
If you do not set it, it will be FALSE
. or you can just manually set it
for each individual shinyCatch
call shinyCatch({...}, trace_back = TRUE)
.
see description and details
The blocking works
similar to shiny's shiny::req()
and shiny::validate()
.
If anything inside fails, it will
block the rest of the code in your reactive expression domain.
It will show error, warning, message by a toastr bar on client end and
also log the text on server console depending on the blocking_level
(dual-end logging).
If blocks at error
level, function will be stopped and other code in the same
reactive context will be blocked.
If blocks at warning
level, warning and
error will be blocked.
message
level blocks all 3 levels.
If blocking_level
is other than these 3, no exceptions will be block, and
if there is any error, NULL
will return and following code will continue to
run.
Since spsComps 0.3.1 to have the message displayed on shiny UI, you don't need
to attach the dependencies manually by adding spsDepend("shinyCatch")
or
spsDepend("toastr")
(old name) on UI. This becomes optional, only in the case
that automatic attachment is not working.
if(interactive()){
ui <- fluidPage(
spsDepend("shinyCatch"), # optional
h4("Run this example on your own computer to better understand exception
catch and dual-end logging", class = "text-center"),
column(
6,
actionButton("btn1","error and blocking"),
actionButton("btn2","error no blocking"),
actionButton("btn3","warning but still returns value"),
actionButton("btn4","warning but blocking returns"),
actionButton("btn5","message"),
),
column(
6,
verbatimTextOutput("text")
)
)
server <- function(input, output, session) {
fn_warning <- function() {
warning("this is a warning!")
return("warning returns")
}
observeEvent(input$btn1, {
shinyCatch(stop("error with blocking"), blocking_level = "error")
output$text <- renderPrint("You shouldn't see me")
})
observeEvent(input$btn2, {
shinyCatch(stop("error without blocking"))
output$text <- renderPrint("I am not blocked by error")
})
observeEvent(input$btn3, {
return_value <- shinyCatch(fn_warning())
output$text <- renderPrint("warning and blocked")
})
observeEvent(input$btn4, {
return_value <- shinyCatch(fn_warning(), blocking_level = "warning")
print(return_value)
output$text <- renderPrint("other things")
})
observeEvent(input$btn5, {
shinyCatch(message("some message"))
output$text <- renderPrint("some message")
})
}
shinyApp(ui, server)
}
# outside shiny examples
shinyCatch(message("this message"))
#> [SPS-INFO] 2023-10-07 07:25:50.292093 this message
#>
try({shinyCatch(stop("this error")); "no block"}, silent = TRUE)
#> [SPS-ERROR] 2023-10-07 07:25:50.394241 this error
#> [1] "no block"
try({shinyCatch(stop("this error"), blocking_level = "error"); "blocked"}, silent = TRUE)
#> [SPS-ERROR] 2023-10-07 07:25:50.397951 this error
# get variable from outside
shinyCatch({my_val <- 123})
my_val
#> [1] 123