FuelLabs/fuels-ts · error · FuelError

DECODE_ERROR

DECODE_ERROR

Error message

Types/values length mismatch during decode. ${JSON.stringify({ count: { types: this.jsonFn.inputs.length, nonVoidInputs: nonVoidInputs.length, values: bytes.length }, value: { args: this.jsonFn.inputs, nonVoidInputs, values: bytes } })}

What it means

Thrown by `FunctionFragment.decodeArguments` (code `DECODE_ERROR`) when a function has zero non-void inputs (so its encoded call arguments should be empty) but the byte buffer passed in is non-empty. The message dumps counts and the raw bytes to aid diagnosis. This is the decode counterpart of the encode path and signals that the bytes do not correspond to this function's input shape.

Source

Thrown at packages/abi-coder/src/FunctionFragment.ts:88

        encoding: this.encoding,
      })
    );

    const argumentValues = padValuesWithUndefined(values, this.jsonFn.inputs);
    return new TupleCoder(coders).encode(argumentValues);
  }

  decodeArguments(data: BytesLike) {
    const bytes = arrayify(data);
    const nonVoidInputs = findNonVoidInputs(this.jsonAbiOld, this.jsonFnOld.inputs);

    if (nonVoidInputs.length === 0) {
      // The VM is current return 0x0000000000000000, but we should treat it as undefined / void
      if (bytes.length === 0) {
        return undefined;
      }

      throw new FuelError(
        ErrorCode.DECODE_ERROR,
        `Types/values length mismatch during decode. ${JSON.stringify({
          count: {
            types: this.jsonFn.inputs.length,
            nonVoidInputs: nonVoidInputs.length,
            values: bytes.length,
          },
          value: {
            args: this.jsonFn.inputs,
            nonVoidInputs,
            values: bytes,
          },
        })}`
      );
    }

    const result = this.jsonFnOld.inputs.reduce(
      (obj: { decoded: unknown[]; offset: number }, input) => {

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Confirm the bytes were produced for the same function fragment you are decoding against.
  2. Regenerate bindings from the deployed contract's ABI and retry.
  3. If the function genuinely has no inputs, ensure you pass an empty buffer (`0x` or `new Uint8Array(0)`).
  4. Inspect the dumped `count`/`value` in the message to compare expected inputs vs. actual bytes.

Example fix

// before
const [, returned] = contractInterface.decodeFunctionResult('noArgFn', someBytes);
// after — verify the bytes belong to this function; pass empty if no inputs
const [, returned] = contractInterface.decodeFunctionResult('noArgFn', '0x');
Defensive patterns

Strategy: try-catch

Validate before calling

const nonVoidInputs = findNonVoidInputs(iface.jsonAbiOld, fn.inputs);
if (nonVoidInputs.length === 0 && arrayify(data).length > 0) {
  // bytes do not belong to this no-arg function; don't call decode
  console.warn('Ignoring non-empty bytes for void-input function');
}

Try / catch

try {
  const decoded = fragment.decodeArguments(data);
} catch (e) {
  if (e.code === 'DECODE_ERROR' && /Types\/values length mismatch during decode/.test(e.message)) {
    // ABI/bytes mismatch — regenerate bindings or pass empty buffer for no-input fns
  }
  throw e;
}

Prevention

When it happens

Trigger: Decoding a return/script-data blob against a function whose ABI declares only void inputs but passing a non-empty buffer; pairing the wrong function fragment with bytes from a different function; ABI/bytecode drift where the contract emits call data the ABI does not model.

Common situations: Reusing a cached ABI after the contract was redeployed with new inputs; decoding transaction script data with a mismatched script ABI; feeding the result of one function into the decoder of another.

Related errors


AI-assisted analysis of FuelLabs/fuels-ts@b3f37c91ac (2026-08-12). Data as JSON: /api/errors/3a34e17e86063692. Report an issue: GitHub.