FuelLabs/sway · error

Too many arguments, cannot handle.

Error message

Too many arguments, cannot handle.

What it means

For call arguments beyond the argument registers, codegen writes each value to its stack slot with SW using a 12-bit immediate offset (byte offset from the saved stack-args base). When cumulative stack-argument bytes exceed 4095 (many and/or large by-value arguments), VirtualImmediate12::try_new fails and this expect panics — a compiler limitation reported with a misleading 'Too many arguments' message. It crashes on the caller side, at the call site.

Source

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

                    let stack_offset_bytes = self.locals_size_bytes() + (stack_offset * 8);
                    assert!(
                        stack_offset_bytes
                            < self.locals_size_bytes() + (self.max_num_extra_args() * 8)
                    );
                    self.cur_bytecode.push(Op {
                        opcode: Either::Left(VirtualOp::SW(
                            VirtualRegister::Constant(
                                ConstantRegister::ARG_REGS
                                    [compiler_constants::NUM_ARG_REGISTERS as usize - 1],
                            ),
                            arg_reg,
                            VirtualImmediate12::try_new(
                                stack_offset,
                                self.md_mgr
                                    .val_to_span(self.context, *arg_val)
                                    .unwrap_or(Span::dummy()),
                            )
                            .expect("Too many arguments, cannot handle."),
                        )),
                        comment: format!(
                            "[call: {fn_name}]: pass argument {idx} via its stack slot"
                        ),
                        owning_span: self.md_mgr.val_to_span(self.context, *arg_val),
                    });
                }
            }
        }

        // Jump to function and insert return label.
        let (fn_label, _) = self.func_to_labels(function);
        self.cur_bytecode.push(Op {
            opcode: Either::Right(OrganizationalOp::Jump {
                to: fn_label,
                type_: JumpType::Call,
            }),
            comment: format!("[call: {fn_name}]: call function"),

View on GitHub (pinned to 47e5e902fa)

Solutions

  1. Bundle arguments into one struct passed by reference: `fn transfer(&transfer_args: TransferArgs)` instead of many by-value params.
  2. Reduce argument count/size (split the call, pass hashes/ids instead of full structs).
  3. Re-check the call after changes with `forc build`; if a modest signature still panics, report upstream with a reproducer.

Example fix

// before
fn configure(a: Config, b: Config, c: Config, ... /* many by-value structs */)
// after
struct Configs { a: Config, b: Config, c: Config }
fn configure(configs: &Configs)
Defensive patterns

Strategy: fallback

Validate before calling

# crude guard for wide signatures before compiling
# (stack bytes ~= 8 per word beyond register args; flag calls with very many/large args)
grep -RnoE 'fn [a-z_]+\([^)]{300,}\)' --include='*.sw' . && echo 'suspiciously wide signature — pass a struct by reference'

Prevention

When it happens

Trigger: Calling a function whose stack-passed arguments total more than 4095 bytes: dozens of u64 arguments, several large structs passed by value, or wide generated/test signatures where args spill well past the argument registers.

Common situations: Generated bindings or tests calling contract-style entry points with wide signatures; refactoring an API to take 'one more' large struct by value; copying a Solidity-style wide function signature into Sway.

Related errors


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