13 Errors
When a fatal error occurs in your application, enables application to recover
A fatal error is a failure from which a program cannot safely recover, so execution must stop immediately.
Let’s take a look at this reprex:
library(ambiorix)
app <- Ambiorix$new()
home_get <- function(req, res) {
xyz
}
app$get("/", home_get)
app$start(port = 5000L)When you run this application and visit http://127.0.0.1:5000/, you get this on the console:
✔ 21-11-2025 22:10:44 Listening on http://127.0.0.1:5000
ℹ 21-11-2025 22:10:47 GET on /
object 'xyz' not foundThe application ran into a fatal error while executing the handler for “/” because of a missing variable.
Luckily, Ambiorix has a generic global error handler, defined roughly as follows:
error_handler <- function(req, res, error) {
message(conditionMessage(error))
res$status <- 500L
res$send("500: Internal Server Error")
}Because of that, the application does not crash, and the user gets this on the client:
500: Internal Server Error
13.1 Custom Handler
Just like route handlers, an error handler must be a function which takes three parameters, in this order:
req: <Required>. The request object.res: <Required>. The response object.error: <Required>. The error object. This is the object returned by functions likestop().
The HTTP status code of the response given by the error handler must be 5XX eg. 500. Quoting MDN Docs:
The HTTP 500 Internal Server Error server error response status code indicates that the server encountered an unexpected condition that prevented it from fulfilling the request.
This error is a generic “catch-all” response to server issues, indicating that the server cannot find a more appropriate
5XXerror to respond with.
The generic global error handler for Ambiorix is okay, but you might need a custom one depending on what you’re building.
For example, if developing a JSON data API, you’d want to return JSON from the handler as follows:
error_handler <- function(req, res, error) {
message(conditionMessage(error))
res$status <- 500L
response <- list(
status = "error",
message = "It's not you, it's us :/"
)
res$json(response)
}As noted in the examples here, we print the real error message to the console, but send back a generic message to the client. This is for security purposes, and it is advised you do the same. It ensures you do not leak critical information about your application to attackers.
13.2 Attach Handler
After defining a custom error handler, attach it to the app instance by setting the error property:
app$error <- error_handler13.3 Route Specific
Remember that the last [optional] parameter for HTTP app methods is error?
You can use it to attach an error handler specific to that route. Even when you have a global error handler, the specific handler is the one that will be called for that route.
For example:
home_get <- function(req, res) {
res$send("Hello, World!")
}
home_get_error_handler <- function(req, res, error) {
message(conditionMessage(error))
res$status <- 503L
res$send("Oops! We're currently offline. Maintenance underway.")
}Then you attach the handler as follows:
app$get("/", home_get, home_get_error_handler)