BoundaryML/baml · error
exhaustive realized-leaf template classification
Error message
exhaustive realized-leaf template classification
What it means
This panic fires in the compiler emitter while lowering a template/test expression whose right-hand side is a fully-realized leaf type (primitive, enum, alias, literal). The code intentionally calls `try_from` with `.expect` to assert that every such leaf can be converted to a `RealizedTy` for classification; hitting the panic means a new leaf variant was added to the type representation but not to the `TryFrom<&Ty> for RealizedTy` conversion, or a non-leaf type leaked into a code path reserved for realized leaves.
Source
Thrown at baml_language/crates/baml_compiler2_emit/src/emit.rs:3743
| TyTemplate::Bool { .. }
| TyTemplate::Null { .. }
| TyTemplate::Uint8Array { .. }
| TyTemplate::Enum(..)
| TyTemplate::EnumVariant(..)
| TyTemplate::RustType { .. }
| TyTemplate::Type { .. }
| TyTemplate::Resource { .. }
| TyTemplate::PromptAst { .. }
| TyTemplate::Void { .. }
| TyTemplate::TypeAlias(..)
| TyTemplate::Never { .. }) => {
// A fully-realized leaf (primitive, enum, alias, literal, ...):
// class-pointer identity for a `TypeAlias`, otherwise its type
// tag when one exactly represents the test. Tagless leaves use
// the canonical structural matcher instead of silently
// compiling to false.
let realized = <&RealizedTy>::try_from(other)
.expect("exhaustive realized-leaf template classification");
if let RealizedTy::TypeAlias(tn, _) = realized {
if let Some(class_obj_idx) = self.class_object_index_for_type_name(tn) {
let c = self
.add_constant(ConstValue::Object(ObjectIndex::from_raw(class_obj_idx)));
let inst = self.emit(Instruction::IsType(c));
self.set_operand(inst, OperandMeta::Const(tn.display_name().to_string()));
} else {
emit_false(self);
}
} else if let RealizedTy::Enum(tn, _) = realized {
// Enum-pointer identity: `is Color` tests the value's enum
// object, so it discriminates `Color` from `Status` - the
// shared `ENUM` type tag cannot. Falls back to constant-false
// if the enum object is absent (e.g. an unreferenced enum).
if let Some(enum_obj_idx) = self.enum_object_index_for_type_name(tn) {
let c = self
.add_constant(ConstValue::Object(ObjectIndex::from_raw(enum_obj_idx)));
let inst = self.emit(Instruction::IsType(c));View on GitHub (pinned to bd85ce9dee)
Solutions
- Extend the `TryFrom<&Ty> for RealizedTy` implementation to handle the offending leaf variant
- Verify the operand reaching emit.rs:3743 is actually a realized leaf; if it carries holes, route it to the structural-matcher path instead
- Check recent type-system changes for new `Ty` variants missing from the conversion
- Run the template/type-test compiler tests to confirm classification coverage
Example fix
// before
let realized = <&RealizedTy>::try_from(other)
.expect("exhaustive realized-leaf template classification");
// after: handle new variant in the conversion
impl TryFrom<&Ty> for RealizedTy {
fn try_from(t: &Ty) -> Result<Self, Self::Error> {
// ...
Ty::NewLeafKind(x) => Ok(RealizedTy::NewLeafKind(x.clone())),
// ...
}
} Defensive patterns
Strategy: type-guard
Validate before calling
fn is_realized_leaf(t: &Ty) -> bool {
matches!(
t,
Ty::Primitive(_) | Ty::Enum(_) | Ty::Alias(_, _) | Ty::Literal(_) | Ty::TypeAlias(_, _)
)
} Type guard
fn as_realized(t: &Ty) -> Option<&RealizedTy> {
<&RealizedTy>::try_from(t).ok()
} Try / catch
// Rust panics are not catchable with ?; use std::panic::catch_unwind only at a process boundary
let result = std::panic::catch_unwind(|| emit_template_test(node));
match result {
Ok(Ok(out)) => out,
_ => report_internal_error("template classification failed"),
} Prevention
- Add a match-all test over Ty variants against the RealizedTy conversion in CI
- Never let hole-carrying types reach the leaf-classification branch
- When adding a Ty variant, grep for `RealizedTy::try_from` and update all conversion sites
When it happens
Trigger: Compiling a `is`/type-test template whose operand is a leaf type that the `RealizedTy::try_from` conversion does not recognize — typically after adding a new `Ty` variant without updating the conversion, or a structural/holes-carrying type reaching the leaf path.
Common situations: Contributors to the BAML compiler adding new type forms (new primitive kinds, literal variants, or alias wrappers) without extending `RealizedTy`; refactors that let non-realized (hole-carrying) types reach the template-classification branch.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- sys_op callee must resolve to a statically-known global func
- interface index {} is not an Object::Interface
- interface `{}` declares no method `{}` for its default
- type-alias offset fits u32
- expected jump instruction at index {instruction_idx}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/8b872c880ef7e233.
Report an issue: GitHub.