BoundaryML/baml · error

ntypeargs fits in u16

Error message

ntypeargs fits in u16

What it means

When emitting MakeVirtualBoundMethod, the count of type_args for the virtual bound method must fit the instruction's u16 ntypeargs field; try_from().expect enforces this as a compiler-internal invariant. Surpassing 65535 type args indicates a bug, not a user-facing condition.

Source

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

        {
            // Stack layout mirrors `VirtualCall`: receiver, then the method-level
            // type args, then the interface type (each resolved against the frame
            // by `LoadType`), then the method name — the opcode pops in reverse.
            self.emit_operand_pull(receiver);
            for template in type_args {
                let const_idx =
                    self.add_constant(ConstValue::Type(bex_vm_types::anchor_template(template)));
                let inst = self.emit(Instruction::LoadType(const_idx));
                self.set_operand(inst, OperandMeta::Const(template.to_string()));
            }
            let iface_const = self.add_constant(ConstValue::Type(bex_vm_types::anchor_template(
                &iface.to_template(),
            )));
            let inst = self.emit(Instruction::LoadType(iface_const));
            self.set_operand(inst, OperandMeta::Const(iface.to_string()));
            self.emit_constant(&Constant::String(method.clone()));
            let inst = self.emit(Instruction::MakeVirtualBoundMethod {
                ntypeargs: u16::try_from(type_args.len()).expect("ntypeargs fits in u16"),
            });
            self.set_operand(inst, OperandMeta::Callable(method.clone()));
            return;
        }
        if let Rvalue::MakeVirtualFunction {
            self_ty,
            iface,
            method,
            type_args,
        } = rvalue
        {
            // Stack layout mirrors `MakeVirtualBoundMethod` with the `Self`
            // TYPE in the receiver's slot: `Self`, then the method-level type
            // args (already `Object::Type` OPERANDS — every one of them a
            // `LoadType` temp, a scoped `type T = …` slot included),
            // then the interface type, then the method name — the opcode pops
            // in reverse.
            let self_const =

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. File a compiler bug with the minimizing repro; reduce the number of type arguments on the virtual bound method
  2. Inspect type_args construction for accidental duplication in the emitter
  3. Refactor the interface/method into smaller parameterized pieces as a workaround
Defensive patterns

Strategy: try-catch

Try / catch

let ntypeargs = u16::try_from(type_args.len())
    .map_err(|_| anyhow!("too many type args for MakeVirtualBoundMethod: {}", type_args.len()))?;

Prevention

When it happens

Trigger: emit.rs emitting MakeVirtualBoundMethod for an interface/type-args list longer than u16::MAX (type_args.len() > 65535).

Common situations: Only via compiler bugs or enormous generated type-argument lists; unreachable in realistic hand-written code.

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


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