BoundaryML/baml · error

a call's argument count fits in u16

Error message

a call's argument count fits in u16

What it means

Internal compiler invariant when emitting a call: the number of value arguments on the call site exceeded u16::MAX (65535). Call instructions encode the argument count in 16 bits, so an oversized argument list (again almost certainly generated or accidentally expanded code) is rejected at emit time with this guard.

Solutions

  1. Reduce the argument count at the call site — near-65535 arguments indicates generated code or accidental list expansion
  2. Bundle the values into a single list or map argument and unpack inside the function
  3. Report it to the BAML maintainers if a reasonable program triggers it
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at baml_language/crates/baml_compiler2_emit/src/emit.rs:2497 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

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

            } => {
                // Push the method type args then the value args (receiver first),
                // then the interface type, then the method name — the layout
                // `OpCode::VirtualCall` expects: it pops the method name, then the
                // interface, then the `ntypeargs` method type args, then reads the
                // receiver (first value arg) to resolve the impl at runtime.
                unwrap_infallible(pull_semantics::walk_call_direct_args(self, args));
                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()));
                if let Some(runtime_id) = runtime_id {
                    unwrap_infallible(pull_semantics::walk_operand_pull(self, runtime_id));
                }
                let nargs = args.len() - ntypeargs;
                let nargs = u16::try_from(nargs)
                    .unwrap_or_else(|_| unreachable!("a call's argument count fits in u16"));
                let ntypeargs = u16::try_from(*ntypeargs)
                    .unwrap_or_else(|_| unreachable!("a call's type-argument count fits in u16"));
                let instruction = if runtime_id.is_some() {
                    Instruction::VirtualCallWithRuntimeId { nargs, ntypeargs }
                } else {
                    Instruction::VirtualCall { nargs, ntypeargs }
                };
                let inst = self.emit(instruction);
                self.record_call_layout(inst, argument_layout.as_ref());
                self.set_operand(inst, OperandMeta::Callable(method.clone()));
                self.emit_store_place(destination);
                self.emit_jump_unless_fallthrough(*target);
            }

            Terminator::Unreachable => {
                // Emit an instruction that will panic at runtime if reached.
                // This should never happen - if it does, there's a bug in the
                // compiler or type system (e.g., non-exhaustive match incorrectly

View on GitHub (pinned to bd85ce9dee)