BoundaryML/baml · error · VmRustFnError
thrown value
Error message
thrown value
What it means
This error variant (VmError::Thrown { value, profiler_kind }) displays as "thrown value" and represents a pre-built exception Value to be thrown directly as a catchable error. Native functions use it to throw user-defined class instances such as baml.json.ParseError without going through the VmPanic/VmBamlError enumeration machinery.
Solutions
- Catch the thrown value and inspect it — it is a real class instance (e.g. baml.json.ParseError) with useful fields.
- Validate/normalize JSON input before calling parsing functions so the throw never happens.
- Note the message is generic by design ("thrown value"); enable profiler-kind/error logging for more context.
- Handle the specific exception class name in your catch logic.
Example fix
// before: raw parse throws and escapes let data = baml.json.Parse(input) // after: guard the input first let data = input.trim().len() > 0 && is_valid_json(input) ? baml.json.Parse(input) : null
Defensive patterns
Strategy: validation
Validate before calling
// Check JSON validity before invoking the parsing native function
fn looks_like_json(s: &str) -> bool {
let t = s.trim();
!t.is_empty()
&& ((t.starts_with('{') && t.ends_with('}'))
|| (t.starts_with('[') && t.ends_with(']'))
|| (t.starts_with('"') && t.ends_with('"')))
} Try / catch
match vm_result {
Err(BexError::Thrown { value, .. }) => {
if let Some(pe) = value.as_instance_of("baml.json.ParseError") {
eprintln!("JSON parse error: {:?}", pe);
}
}
other => other?,
} Prevention
- Validate/normalize JSON input before parsing.
- Catch and inspect the thrown class instance rather than relying on the generic message.
- Enable profiler/error-kind logging to see which native function threw.
- Return nullable results from parse helpers instead of letting throws escape.
When it happens
Trigger: A native function (e.g. JSON parsing) needs to throw a user-defined exception instance; the VM raises it as a catchable error value; when uncaught it surfaces with the generic message "thrown value".
Common situations: Parsing malformed JSON in BAML and baml.json.ParseError escaping without a catch handler; host-defined exception classes thrown by native helpers; the generic message hides the real cause until the thrown Value is inspected.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- baml.json.deserialize failed
- baml.json.serialize failed
- baml.panics.AssertionFailed
- baml.panics.Cancelled
- baml.panics.DivisionByZero
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/208b4016c674d07a.
Report an issue: GitHub.
Appendix: source
Thrown at baml_language/crates/bex_vm_types/src/errors.rs:477
}
/// An error returned by a Rust function. Will generally be turned into a [`VmError`].
/// This is separate from [`VmError`] so native Rust functions can return standard errors
/// without needing to handle heap allocation.
#[derive(Debug, Error, PartialEq, Clone)]
pub enum VmRustFnError {
#[error("{0}")]
Panic(#[from] VmPanic),
#[error("{0}")]
BamlError(#[from] VmBamlError),
#[error("{0}")]
InternalError(#[from] VmInternalError),
/// A pre-built exception `Value` to throw directly as a catchable error.
///
/// Used by native functions that need to throw user-defined class instances
/// (e.g. `baml.json.ParseError`) without going through the
/// `VmPanic` / `VmBamlError` enumeration machinery.
#[error("thrown value")]
Thrown {
value: Value,
profiler_kind: ProfilerErrorKind,
},
}
impl VmRustFnError {
#[must_use]
pub const fn thrown_fresh(value: Value) -> Self {
Self::Thrown {
value,
profiler_kind: ProfilerErrorKind::Fresh,
}
}
#[must_use]
pub const fn thrown_rethrow(value: Value) -> Self {
Self::Thrown {View on GitHub (pinned to bd85ce9dee)