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

  1. Read the message to identify the failing check and fix the calling BAML code.
  2. Catch `baml.panics.UserPanic` in BAML to convert the panic into a controlled error path.
  3. 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

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


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/f5a30885567ee072. Report an issue: GitHub.