BoundaryML/baml · error

ntypeargs fits u16

Error message

ntypeargs fits u16

What it means

In `make_generic_function` the compiler narrows a `usize` generic-type-argument count to `u16` for the `MakeGenericFunction` bytecode instruction via `u16::try_from(...).expect(...)`. The panic means a generic function was declared with more than 65535 type parameters, which the instruction encoding cannot represent.

Source

Thrown at baml_language/crates/baml_compiler2_emit/src/emit.rs:3833

    fn make_closure_with_type_args(
        &mut self,
        lambda_idx: usize,
        capture_count: usize,
        ntypeargs: usize,
    ) -> Result<(), Self::Error> {
        self.emit_make_closure_bytecode(lambda_idx, capture_count, ntypeargs);
        Ok(())
    }

    fn make_generic_function(
        &mut self,
        item: &baml_compiler2_mir::ItemRef<'ctx>,
        ntypeargs: usize,
    ) -> Result<(), Self::Error> {
        let func_name = item.to_string();
        let global_idx = self.function_global_index(item, "MakeGenericFunction: global not found");
        let ntypeargs = u16::try_from(ntypeargs).expect("ntypeargs fits u16");
        let inst = self.emit(Instruction::MakeGenericFunction {
            function: GlobalIndex::from_raw(global_idx),
            ntypeargs,
        });
        self.set_operand(inst, OperandMeta::Global(func_name));
        Ok(())
    }

    fn make_generic_function_from_value(&mut self, ntypeargs: usize) -> Result<(), Self::Error> {
        // The callable value and `ntypeargs` `Object::Type` values are already
        // on the stack (pushed by `walk_rvalue_pull`); just emit the opcode.
        let ntypeargs = u16::try_from(ntypeargs).expect("ntypeargs fits u16");
        self.emit(Instruction::MakeGenericFunctionFromValue { ntypeargs });
        Ok(())
    }

    fn load_capture(&mut self, idx: usize) -> Result<(), Self::Error> {
        if self.loading_for_closure_capture {

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Reduce the number of type parameters on the offending generic function/declaration
  2. Audit how `ntypeargs` is computed for the item; fix the count if it is inflated
  3. If >65535 type args is a real requirement, widen the instruction field to u32 in both emitter and VM

Example fix

// before
let ntypeargs = u16::try_from(ntypeargs).expect("ntypeargs fits u16");
// after
let ntypeargs = u16::try_from(ntypeargs).map_err(|_| EmitError::TooManyTypeArgs(ntypeargs))?;
Defensive patterns

Strategy: validation

Validate before calling

if ntypeargs > u16::MAX as usize {
    return Err(format!("too many type args: {ntypeargs} > 65535"));
}

Type guard

fn fits_u16(n: usize) -> Option<u16> {
    u16::try_from(n).ok()
}

Try / catch

// Rust: validate before emit; catch_unwind only as a last resort
std::panic::catch_unwind(|| make_generic_function(item, ntypeargs))
    .unwrap_or_else(|_| report_internal_error("ntypeargs exceeded u16"));

Prevention

When it happens

Trigger: Emitting `MakeGenericFunction` for an item whose `ntypeargs` (number of generic type parameters) exceeds `u16::MAX`; in practice only reachable through synthesized/concatenated generic signatures or an arity-counting bug.

Common situations: Auto-generated code with pathologically large generic arity; an off-by-large bug when computing the parameter count for a MIR item.

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/2b40a34a6cd6b0d9. Report an issue: GitHub.