Error Handling
Errors in Risor are values you can inspect, and exceptions you can catch.
Use try/catch/finally to intercept errors and throw to raise them --
and because try/catch is an expression, error recovery often fits in a
single line.
Creating Errors
The error built-in creates an error value. It supports format string
interpolation similar to Go's fmt.Sprintf:
let err = error("something went wrong")
let err = error("file %s not found", filename)Error values are always truthy and can be inspected with the .message() method.
Throwing Errors
throw raises an error and interrupts normal execution:
throw error("something went wrong")Execution unwinds up the call stack until a try/catch block catches it.
If nothing catches it, the script terminates with the error.
Try / Catch / Finally
Wrap risky code in try/catch/finally to handle errors gracefully:
try {
risky_operation()
} catch e {
error("failed: %s", e.message())
} finally {
cleanup()
}Catch Block
catch runs when an error is thrown inside the try block. The variable
after catch binds to the error value:
try {
let data = parse(input)
} catch err {
error("parse failed: %s", err.message())
}Finally Block
finally runs regardless of whether an error occurred. Useful for cleanup:
let conn = open_connection()
try {
conn.send(data)
} catch e {
error("send failed: %s", e.message())
} finally {
conn.close()
}finally is optional. Use try/catch without it, or try/finally
without catch. Both work.
Try as an Expression
Like if/else and match, try/catch is an expression. It evaluates to
the last expression in whichever branch runs:
let result = try {
parse(input)
} catch e {
default_value
}This makes fallback values a one-liner:
let config = try { load_config() } catch e { {} }Error Methods
Error values support the following method:
| Method | Description |
|---|---|
.message() | Returns the error message as a string |
Example:
let err = error("disk full")
err.message() // "disk full"Patterns
Wrapping Errors
Add context when re-throwing:
try {
connect(host)
} catch e {
throw error("connection to %s failed: %s", host, e.message())
}Safe Value Extraction
try/catch as an expression gives you safe extraction with a fallback:
let port = try { int(config["port"]) } catch e { 8080 }Validation
Fail fast by validating preconditions up front:
function divide(a, b) {
if (b == 0) {
throw error("division by zero")
}
return a / b
}