FuelLabs/sway · error

Stack size too big for these many arguments, cannot handle.

Error message

Stack size too big for these many arguments, cannot handle.

What it means

In call-sequence codegen, when a function's locals fit in 12 bits the compiler stores LocalsBase + locals_size into the last argument register via ADDI with a VirtualImmediate12. This branch is guarded by `locals_size_bytes() <= TWELVE_BITS`, the very bound VirtualImmediate12 enforces, so the expect is an internal invariant assert that should be unreachable. If it fires, TWELVE_BITS and the immediate's actual width have diverged — an internal compiler error (ICE), not a user-code condition.

Source

Thrown at sway-core/src/asm_generation/fuel/functions.rs:101

                    arg_reg,
                    format!("[call: {fn_name}]: pass argument {idx}"),
                    self.md_mgr.val_to_span(self.context, *arg_val),
                ));
            }
        } else {
            // Register ARG_REGS[NUM_ARG_REGISTERS-1] must contain LocalsBase + locals_size
            // so that the callee can index the stack arguments from there.
            // It's also useful for us to save the arguments to the stack next.
            if self.locals_size_bytes() <= TWELVE_BITS {
                self.cur_bytecode.push(Op {
                    opcode: Either::Left(VirtualOp::ADDI(
                        VirtualRegister::Constant(
                            ConstantRegister::ARG_REGS
                                [(compiler_constants::NUM_ARG_REGISTERS - 1) as usize],
                        ),
                        VirtualRegister::Constant(ConstantRegister::LocalsBase),
                        VirtualImmediate12::try_new(self.locals_size_bytes(), Span::dummy())
                            .expect("Stack size too big for these many arguments, cannot handle."),
                    )),
                    comment: format!("[call: {fn_name}]: save address of stack arguments in last argument register"),
                    owning_span: self.md_mgr.val_to_span(self.context, *instr_val),
                });
            } else {
                self.cur_bytecode.push(Op {
                    opcode: Either::Left(VirtualOp::MOVI(
                        VirtualRegister::Constant(
                            ConstantRegister::ARG_REGS
                                [(compiler_constants::NUM_ARG_REGISTERS - 1) as usize],
                        ),
                        VirtualImmediate18::try_new(self.locals_size_bytes(), Span::dummy())
                            .expect("Stack size too big for these many arguments, cannot handle."),
                    )),
                    comment: format!(
                        "[call: {fn_name}]: temporarily save locals size to add up next"
                    ),
                    owning_span: self.md_mgr.val_to_span(self.context, *instr_val),

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Treat as an ICE: reduce to a minimal .sw case and report at FuelLabs/sway with the compiler version.
  2. If maintaining a fork, verify TWELVE_BITS == 4095 and that VirtualImmediate12::try_new uses the same bound.
  3. Switch back to the last released toolchain (`fuelup default <version>`) to confirm it is fork-specific.

Example fix

// invariant check (compiler_constants)
// before
pub const TWELVE_BITS: u32 = 8_191;               // diverges from immediate width -> expect fires
// after
pub const TWELVE_BITS: u32 = 4_095;               // matches VirtualImmediate12 bound
Defensive patterns

Strategy: fallback

Validate before calling

// fork maintainers: assert the invariant in tests so divergence fails loudly in CI
#[test]
fn twelve_bits_matches_immediate() {
    assert_eq!(compiler_constants::TWELVE_BITS, (1u32 << 12) - 1);
    assert!(VirtualImmediate12::try_new(compiler_constants::TWELVE_BITS as u64, Span::dummy()).is_ok());
}

Prevention

When it happens

Trigger: A fork/refactor of sway-core changes compiler_constants::TWELVE_BITS or the width of VirtualImmediate12 so the guard no longer implies try_new success; essentially unreachable on released compilers regardless of the Sway source compiled.

Common situations: Contributing to sway-core asm generation; bisecting a compiler crash that lands here; reviewing changes that touch immediate types or compiler constants.

Related errors


AI-assisted analysis of FuelLabs/sway@47e5e902fa (2026-08-16). Data as JSON: /api/errors/d619474d20f39f79. Report an issue: GitHub.