Errors and Error Handling
16.1 Error Sets and Error Unions
An error is a value, like an enum across the program. anyerror is the global set of all errors.
Errors can't carry payloads. Use a "diagnostics" out-parameter for details (16.5).
const FileError = error{
NotFound,
PermissionDenied,
};
const ParseError = error{ InvalidChar, Overflow };
const AppError = FileError || ParseError; // merge error sets
fn parseDigit(c: u8) ParseError!u8 { // error union: ParseError or u8
if (c < '0' or c > '9') return error.InvalidChar;
return c - '0';
}
fn loadConfig(path: []const u8) !Config { // inferred error set
_ = path;
return error.NotFound;
}16.2 Handling Errors
// try: return the error to the caller (≡ catch |e| return e)
const d = try parseDigit('7');
// catch: default value
const e = parseDigit('x') catch 0;
// catch with a capture
const f = parseDigit('x') catch |err| blk: {
std.debug.print("failed: {s}\n", .{@errorName(err)});
break :blk 0;
};
// catch unreachable: assert it can't fail
const g = parseDigit('5') catch unreachable;
// switch on errors
parseDigit('x') catch |err| switch (err) {
error.InvalidChar => std.debug.print("bad char\n", .{}),
error.Overflow => {},
};
// if/else with error capture
if (parseDigit('3')) |val| {
_ = val;
} else |err| {
_ = err;
}
_ = .{ d, e, f, g };16.3 Error Return Traces
In Debug and ReleaseSafe, an error returned from main prints an error return trace showing every try point it passed through. It's extremely helpful for debugging.
@errorReturnTrace() gives programmatic access.
16.4 main and Errors
pub fn main() !void {
try run(); // an error here prints its name + trace and exits with code 1
}16.5 Patterns for Rich Error Information
The standard library uses this pattern (e.g., std.json.Diagnostics, std.zon parse diagnostics).
const Diagnostics = struct {
line: usize = 0,
message: []const u8 = "",
};
fn parse(src: []const u8, diag: *Diagnostics) !Ast {
if (src.len == 0) {
diag.* = .{ .line = 1, .message = "empty input" };
return error.ParseFailed;
}
// ...
}16.6 Panics
@panic("unrecoverable state"); // custom panic
std.debug.assert(x > 0); // panics if false in Debug/ReleaseSafe (UB hint in fast modes)
pub const panic = std.debug.FullPanic(myPanicFn); // override the panic handler in the root file (0.14+)