BoundaryML/baml · error
type-alias offset fits u32
Error message
type-alias offset fits u32
What it means
This is a Rust panic raised by `u32::try_from(off).expect("type-alias offset fits u32")` in baml_compiler2_emit's object-pool emitter. When a new TypeAlias pool object is pushed into a compilation unit's `type_alias_objects` vector, its index is converted to u32 for the emitted `LocalRef::TypeAlias`. The panic fires only if the number of type-alias objects in one unit exceeds u32::MAX (about 4.29 billion), which would make the emitted u32 offset unable to address the object. It is an internal invariant guard, not a user-facing validation error.
Source
Thrown at baml_language/crates/baml_compiler2_emit/src/lib.rs:2450
PoolObjKind::Class => {
let off = units[u].classes.len();
units[u].classes.push(obj);
LocalRef::Class(u32::try_from(off).expect("class offset fits u32"))
}
PoolObjKind::Enum => {
let off = units[u].enums.len();
units[u].enums.push(obj);
LocalRef::Enum(u32::try_from(off).expect("enum offset fits u32"))
}
PoolObjKind::Interface => {
let off = units[u].interfaces.len();
units[u].interfaces.push(obj);
LocalRef::Interface(u32::try_from(off).expect("interface offset fits u32"))
}
PoolObjKind::TypeAlias => {
let off = units[u].type_alias_objects.len();
units[u].type_alias_objects.push(obj);
LocalRef::TypeAlias(u32::try_from(off).expect("type-alias offset fits u32"))
}
PoolObjKind::NamedFn(_) | PoolObjKind::CodeAnon => {
let off = units[u].code.len();
units[u].code.push(obj);
LocalRef::Code(u32::try_from(off).expect("code offset fits u32"))
}
};
obj_localref.push(local_ref);
}
// ---- Global slot -> owner + local flat index ----------------------------
// slot -> fq name (functions, interface bodies, and lets).
let mut slot_to_name: Vec<Option<String>> = vec![None; program.globals.len()];
for (name, &slot) in &program.function_global_indices {
slot_to_name[slot] = Some(name.clone());
}
for (slot, name) in &interface_body_slot_names {
slot_to_name[*slot] = Some(name.clone());View on GitHub (pinned to bd85ce9dee)
Solutions
- Check the input for runaway or duplicated type-alias definitions — a generator loop may be emitting the same type alias millions of times; fix the generator.
- Split the compilation unit: move type aliases into separate units/files so no single unit exceeds u32::MAX objects.
- Reduce total type-alias count in the offending source by deduplicating aliases that resolve to the same underlying type.
- If this occurs on normal-sized input, report it as a compiler bug: the pool indexing may be looping and re-pushing objects; file an issue with the reproducing source.
Example fix
// before: emitting one alias object per textual occurrence
for alias in all_aliases_everywhere {
units[u].type_alias_objects.push(obj);
}
// after: deduplicate aliases before pooling
let seen = &mut HashSet::new();
for alias in all_aliases_everywhere.into_iter().filter(|a| seen.insert(a.key())) {
units[u].type_alias_objects.push(obj);
} Defensive patterns
Strategy: validation
Validate before calling
assert!(
units[u].type_alias_objects.len() < u32::MAX as usize,
"compilation unit has too many type-alias objects for u32 offsets"
); Try / catch
// Rust panics cannot be caught with catch_unwind safely across FFI; validate before emitting:
let result = std::panic::catch_unwind(|| emit_pool(units));
match result {
Ok(pool) => pool,
Err(_) => fallback_to_diagnostic_error("pool overflow"),
} Prevention
- Deduplicate type-alias definitions before pooling so no unit grows unboundedly.
- Split very large generated sources across multiple compilation units.
- Add a compile-time (early) diagnostic when a unit's object counts approach u32::MAX instead of panicking mid-emit.
- When generating BAML programmatically, assert emitted alias counts per unit stay far below 2^32.
When it happens
Trigger: Compiling a single compilation unit whose `type_alias_objects` pool grows beyond 4,294,967,295 entries — i.e. a BAML source containing (or a code generator emitting) more than u32::MAX type-alias definitions in one unit.
Common situations: Practically never hit by hand-written BAML code; would require runaway code generation, a bug in a macro/expansion layer that duplicates type-alias definitions in a loop, or a corrupted/huge generated source. Also seen by contributors running fuzzers with artificially crafted giant inputs.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- sys_op callee must resolve to a statically-known global func
- exhaustive realized-leaf template classification
- interface index {} is not an Object::Interface
- interface `{}` declares no method `{}` for its default
- class offset fits u32
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e0aec6b636672add.
Report an issue: GitHub.