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

  1. 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.
  2. Split the compilation unit: move type aliases into separate units/files so no single unit exceeds u32::MAX objects.
  3. Reduce total type-alias count in the offending source by deduplicating aliases that resolve to the same underlying type.
  4. 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

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


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