FuelLabs/fuels-ts · error · FuelError

DECODE_ERROR

DECODE_ERROR

Error message

Invalid array data size.

What it means

Thrown by `ArrayCoder.decode` (code `DECODE_ERROR`) when the byte buffer is too small for the declared array's encoded length (and there is no nested `Option` to allow short reads) OR the buffer exceeds `MAX_BYTES`. Guards against underflow and runaway buffers during decoding.

Source

Thrown at packages/abi-coder/src/encoding/coders/ArrayCoder.ts:42

    this.length = length;
    this.#hasNestedOption = hasNestedOption([coder]);
  }

  encode(value: InputValueOf<TCoder>): Uint8Array {
    if (!Array.isArray(value)) {
      throw new FuelError(ErrorCode.ENCODE_ERROR, `Expected array value.`);
    }

    if (this.length !== value.length) {
      throw new FuelError(ErrorCode.ENCODE_ERROR, `Types/values length mismatch.`);
    }

    return concat(Array.from(value).map((v) => this.coder.encode(v)));
  }

  decode(data: Uint8Array, offset: number): [DecodedValueOf<TCoder>, number] {
    if ((!this.#hasNestedOption && data.length < this.encodedLength) || data.length > MAX_BYTES) {
      throw new FuelError(ErrorCode.DECODE_ERROR, `Invalid array data size.`);
    }

    let newOffset = offset;
    const decodedValue = Array(this.length)
      .fill(0)
      .map(() => {
        let decoded;
        [decoded, newOffset] = this.coder.decode(data, newOffset);
        return decoded;
      });

    return [decodedValue as DecodedValueOf<TCoder>, newOffset];
  }
}

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Verify the byte buffer length matches `arrayCoder.encodedLength` (i.e. `length * elementCoder.encodedLength`).
  2. Re-check the offset used when slicing; ensure `offset + encodedLength <= data.length`.
  3. Regenerate bindings to make sure the ABI matches the deployed contract's actual return layout.
  4. If the buffer is genuinely huge, confirm you are not passing the whole payload instead of the relevant slice.

Example fix

// before
const [decoded] = arrayCoder.decode(data, data.length - 4); // slice too short
// after — pass a buffer/offset that gives the full encodedLength
const [decoded] = arrayCoder.decode(data, offset);
Defensive patterns

Strategy: try-catch

Validate before calling

const need = arrayCoder.encodedLength;
if (data.length < need || data.length > MAX_BYTES) {
  throw new Error(`Buffer of ${data.length} bytes cannot decode [T; ${arrayCoder.length}] (need ${need})`);
}

Try / catch

try {
  const [val, off] = arrayCoder.decode(data, offset);
} catch (e) {
  if (e.code === 'DECODE_ERROR' && /Invalid array data size/.test(e.message)) {
    // buffer/offset wrong — re-derive the slice and retry
  }
  throw e;
}

Prevention

When it happens

Trigger: Decoding a return/script-data buffer that was truncated; passing a slice computed with a wrong offset that cuts into the middle of the array; feeding an absurdly large buffer (`> MAX_BYTES`) such as a whole transaction where a slice was expected.

Common situations: ABI/bytecode drift causing return data of unexpected size; wrong offset passed when manually decoding nested types; reading from a receipt whose `data` field is shorter than the ABI implies.

Related errors


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