FuelLabs/fuels-ts · error · FuelError

ENCODE_ERROR

ENCODE_ERROR

Error message

Invalid ${this.baseType}.

What it means

Thrown by NumberCoder.encode() when the underlying toBytes()/bn() call fails to convert the input value into a byte array. NumberCoder encodes Sway unsigned integers (u8, u16, u32); if the value is not a valid numeric representation, the conversion throws and this ENCODE_ERROR wraps it. The message includes the baseType (e.g. 'u8') to identify which integer coder rejected the value.

Source

Thrown at packages/abi-coder/src/encoding/coders/NumberCoder.ts:46

  constructor(
    baseType: NumberCoderType,
    options: EncodingOptions = {
      padToWordSize: false,
    }
  ) {
    const length = options.padToWordSize ? WORD_SIZE : getLength(baseType);
    super('number', baseType, length);
    this.baseType = baseType;
    this.options = options;
  }

  encode(value: number | string): Uint8Array {
    let bytes;

    try {
      bytes = toBytes(value);
    } catch (error) {
      throw new FuelError(ErrorCode.ENCODE_ERROR, `Invalid ${this.baseType}.`);
    }

    if (bytes.length > this.encodedLength) {
      throw new FuelError(ErrorCode.ENCODE_ERROR, `Invalid ${this.baseType}, too many bytes.`);
    }

    return toBytes(bytes, this.encodedLength);
  }

  decode(data: Uint8Array, offset: number): [number, number] {
    if (data.length < this.encodedLength) {
      throw new FuelError(ErrorCode.DECODE_ERROR, `Invalid number data size.`);
    }

    const bytes = data.slice(offset, offset + this.encodedLength);

    if (bytes.length !== this.encodedLength) {
      throw new FuelError(ErrorCode.DECODE_ERROR, `Invalid number byte data size.`);

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Ensure the value is a finite number or a valid numeric/hex string before calling encode().
  2. If the field is genuinely nullable, declare it as Option<T> in the Sway ABI so OptionCoder is used instead of NumberCoder.
  3. Validate with Number.isFinite() or a BN conversion check at the application boundary before encoding.

Example fix

// before
const coder = new NumberCoder('u32');
coder.encode(maybeUndefined); // throws ENCODE_ERROR

// after
const coder = new NumberCoder('u32');
const val = maybeUndefined ?? 0;
if (!Number.isFinite(val)) throw new Error('Expected a finite number');
coder.encode(val);
Defensive patterns

Strategy: validation

Validate before calling

function isValidNumberInput(value: unknown): boolean {
  if (typeof value === 'number') return Number.isFinite(value);
  if (typeof value === 'string') {
    const trimmed = value.trim();
    if (trimmed === '') return false;
    return !isNaN(Number(trimmed));
  }
  return false;
}

Type guard

function isNumberInput(value: unknown): value is number | string {
  if (typeof value === 'number') return Number.isFinite(value);
  if (typeof value === 'string') {
    const t = value.trim();
    return t !== '' && !isNaN(Number(t));
  }
  return false;
}

Try / catch

try {
  const encoded = numberCoder.encode(value);
} catch (e) {
  if (e instanceof FuelError && e.code === ErrorCode.ENCODE_ERROR) {
    // value was not a valid number; log and provide default
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling NumberCoder('u8').encode(undefined), passing NaN from a failed parseInt, providing a non-numeric string like 'abc', or passing an object. Also triggered indirectly when encoding a struct or tuple whose numeric field is undefined and the field coder is a NumberCoder.

Common situations: An optional struct field is left undefined but the ABI type is a bare u32 (not Option<u32>). A value arrives from JSON as a string containing non-numeric characters. Arithmetic produces NaN that flows into encode().

Related errors


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