BoundaryML/baml · error · VmPanic
baml.panics.UserPanic
baml.panics.UserPanic
Error message
baml.sys.panic: {message} What it means
A user-caused panic raised by `baml.sys.panic(message)` from BAML code, or by the stdlib panicking on a user-violated native invariant (e.g. a reflection kind view's `_ty` field overwritten with a type of a different kind). The message is the programmer-provided description.
Source
Thrown at baml_language/crates/bex_vm_types/src/errors.rs:63
#[error("key not found in map")]
MapKeyNotFound,
#[error("stack overflow")]
StackOverflow,
#[error("assertion failed")]
AssertionFailed,
#[error("unreachable code executed")]
Unreachable,
#[error("operation cancelled")]
Cancelled,
/// A user-caused panic from `baml.sys.panic`, and the stdlib's panic of
/// record for a user-violated native invariant (e.g. a reflection kind
/// view's `_ty` field overwritten with a type of a different kind).
#[error("baml.sys.panic: {message}")]
UserPanic { message: String },
/// A clean process-termination request from `baml.sys.exit(code)`.
///
/// Catchable in user code as `baml.panics.Exit` — patterned after
/// Python's `SystemExit`: code can intercept it for cleanup or
/// testing, and if nothing catches it the engine surfaces the code
/// as `EngineError::Exit` and the host terminates with it.
///
/// BAML `int` is `i64`, so the signal carries the full value the
/// user wrote; the host narrows to `i32` for `std::process::exit`.
#[error("baml.sys.exit({code})")]
Exit { code: i64 },
/// The graceful-ish way to handle potential OOM errors, instead of hard-crashing.
#[error("memory allocation failed: {message}")]
AllocFailure { message: String },
View on GitHub (pinned to bd85ce9dee)
Solutions
- Read the message to identify the failing check and fix the calling BAML code.
- Catch `baml.panics.UserPanic` in BAML to convert the panic into a controlled error path.
- Do not overwrite native invariant fields (like `_ty` on reflection views); use the provided APIs.
Example fix
// before view._ty = some_int_type; // wrong kind // after view._ty = some_record_type; // keep the kind consistent with the view
Defensive patterns
Strategy: try-catch
Validate before calling
// BAML: validate before panicking
if (value == null) { return err("value required"); } Type guard
// BAML: guard reflection views before mutation
if (is_kind_view(v) && kind_of(ty) == expected_kind) { v._ty = ty; } Try / catch
// BAML
try {
risky();
} catch (e: baml.panics.UserPanic) {
return err(e.message);
} Prevention
- Prefer returning errors over baml.sys.panic for expected failure paths
- Never write mismatched types into native `_ty` fields
- Keep panic messages actionable — they become the error text
When it happens
Trigger: BAML code calls `baml.sys.panic("...")` directly; or user code mutates a native record's invariant field such as writing a mismatched type into a reflection view's `_ty` field.
Common situations: Deliberate fail-fast on invalid input in BAML functions, misuse of the reflection/stdin native APIs, writing to internals that the stdlib assumes are well-formed.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- baml.panics.IntegerOverflow
- baml.panics.IndexOutOfBounds
- baml.panics.InvalidFieldAccess
- baml.panics.MapKeyNotFound
- baml.panics.StackOverflow
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/f5a30885567ee072.
Report an issue: GitHub.