FuelLabs/fuels-ts · error · FuelError
ENCODE_ERROR
ENCODE_ERROR
Error message
Invalid ${this.type}. What it means
Thrown by B512Coder.encode (this.type resolves to 'struct B512', so the message reads "Invalid struct B512.") when arrayify() rejects the input. arrayify only accepts a Uint8Array or a string matching /^0x([0-9a-f][0-9a-f])*$/i; anything else is caught and re-thrown as ENCODE_ERROR before any length check runs. A B512 is a 64-byte FuelVM signature value, so the input must be parseable bytes first.
Source
Thrown at packages/abi-coder/src/encoding/coders/B512Coder.ts:19
import { ErrorCode, FuelError } from '@fuel-ts/errors';
import { bn, toHex } from '@fuel-ts/math';
import { arrayify } from '@fuel-ts/utils';
import { WORD_SIZE } from '../../utils/constants';
import { Coder } from './AbstractCoder';
export class B512Coder extends Coder<string, string> {
constructor() {
super('b512', 'struct B512', WORD_SIZE * 8);
}
encode(value: string): Uint8Array {
let encodedValue;
try {
encodedValue = arrayify(value);
} catch (error) {
throw new FuelError(ErrorCode.ENCODE_ERROR, `Invalid ${this.type}.`);
}
if (encodedValue.length !== this.encodedLength) {
throw new FuelError(ErrorCode.ENCODE_ERROR, `Invalid ${this.type}.`);
}
return encodedValue;
}
decode(data: Uint8Array, offset: number): [string, number] {
if (data.length < this.encodedLength) {
throw new FuelError(ErrorCode.DECODE_ERROR, `Invalid b512 data size.`);
}
let bytes = data.slice(offset, offset + this.encodedLength);
const decoded = bn(bytes);
if (decoded.isZero()) {
bytes = new Uint8Array(64);
}View on GitHub (pinned to b3f37c91ac)
Solutions
- Normalize the value to a '0x'-prefixed hex string before encode, prepending '0x' if missing.
- If you hold raw bytes, pass a Uint8Array (arrayify accepts it) or convert with hexlify first.
- Validate the format with a regex and confirm it is exactly 128 hex chars before calling encode.
- Trace where the signature originated to stop the malformed value at the source instead of patching at encode time.
Example fix
// before
sigCoder.encode(sigStr) // sigStr lost its '0x' prefix in transit
// after
const clean = sigStr.startsWith('0x') ? sigStr : `0x${sigStr}`
sigCoder.encode(clean) Defensive patterns
Strategy: validation
Validate before calling
const B512_HEX = /^0x[0-9a-fA-F]{128}$/
function isValidB512(v: unknown): v is string {
return typeof v === 'string' && B512_HEX.test(v)
}
if (!isValidB512(value)) throw new Error('expected 0x-prefixed 64-byte hex')
sigCoder.encode(value) Type guard
const isHexString = (v: unknown): v is string =>
typeof v === 'string' && /^0x([0-9a-fA-F]{2})*$/.test(v) Try / catch
try { sigCoder.encode(value) }
catch (e) { if ((e as FuelError).code === ErrorCode.ENCODE_ERROR) { /* normalize value or surface input error */ } throw e } Prevention
- Keep signatures as '0x'-prefixed hex strings throughout your data flow.
- Validate hex format at the trust boundary (API/Form input), not only at encode.
- Avoid JSON round-trips that drop or alter the '0x' prefix.
When it happens
Trigger: Calling b512.encode(value), or encoding any function input typed as b512 via Interface/Contract, where value is a string that fails the hex regex: missing '0x' prefix, an odd number of hex digits, non-hex characters (e.g. spaces, '0X' capitalized 'X' path is fine but raw base64/filename text is not), or a non-string/non-Uint8Array runtime value.
Common situations: A signature that lost its '0x' during JSON round-trip; passing a base64 or PEM string instead of hex; a value that was coerced to a number and back to a decimal string; copy/paste truncating the hex; feeding a wallet recovery phrase or address where a signature was expected.
Related errors
AI-assisted analysis of FuelLabs/fuels-ts@b3f37c91ac (2026-08-12).
Data as JSON: /api/errors/247b5ece74417905.
Report an issue: GitHub.