Errors
class EncodeError extends Error {}class DecodeError extends Error { readonly offset: number }| Error | Thrown when |
|---|---|
EncodeError | validation failed on the way in, or the schema cannot be encoded |
DecodeError | the bytes are malformed, or validation failed on the way out |
DecodeError.offset is the byte position reached. For a validation failure, it equals the payload length because structural decoding must consume every byte before validation runs.
try { decode(Person, bytes);} catch (error) { if (error instanceof DecodeError) { console.error(`bad payload at byte ${error.offset}: ${error.message}`); }}To avoid exceptions, use safeDecode. It returns either { success: true, data } or { success: false, error } and wraps values that are not already Error objects.
Schema-construction errors
Section titled “Schema-construction errors”These are all EncodeError instances thrown when the codec is built. See Rejected Shapes for workarounds.
| Message | Cause |
|---|---|
Records and open objects are not currently supported | z.looseObject, z.record, v.record |
Only nullable JSON Schema unions are currently supported | a general or discriminated union |
Only nullable JSON Schema type arrays are currently supported | a type array with >1 non-null entry |
Arrays require an item schema | an array with no items |
Empty enums are unsupported | an enum with no members |
Unsupported JSON Schema literal | a literal that is not string, number, boolean, or null |
Unsupported Standard JSON Schema type X | a type with no wire shape |
Unsupported Standard JSON Schema node | a non-object node where a schema was expected |
Required property "x" has no schema | required names a property absent from properties |
Schemas with different input and output wire shapes require a bidirectional codec and are not yet supported | a default or widening refinement makes the sides differ |
Standard Schema provides validation but not structure; pass a Standard JSON Schema implementation as the second argument | Valibot, Zod < 4.2, ArkType < 2.1.28 |
This schema already decodes to null; wrapping it in nullable() would give null two encodings | m.literal(null).nullable(), or a second null marker over one already reachable |
This schema already decodes to undefined; wrapping it in optional() would give undefined two encodings | a second presence marker over one already reachable |
fingerprinted() needs a codec built from a Standard JSON Schema; compile() returns one, the low-level m API does not | fingerprinted(m.object(...)) |
Fingerprint bytes must be 1, 2, 3 or 4, received X | out-of-range bytes option |
Rich types
Section titled “Rich types”<the vendor's own message> — shorn encodes the wire shape; convert rich typesat the edge (README: Dates, BigInt, Map and Set)shorn preserves the validator’s original reason and appends guidance. This applies to Date, bigint, Map, Set, undefined, NaN, and transforms. See Date, BigInt, Map, Set.
This Standard Schema validates asynchronously; use encodeAsync/decodeAsync withthe Standard Schema. Neither accepts a compiled or fingerprinted codec.The second sentence clarifies an important limitation: async entry points accept schemas, not compiled or fingerprinted codecs.
Encode-time value errors
Section titled “Encode-time value errors”| Message | Cause |
|---|---|
Unknown object property "x" | an extra property where the vendor left additionalProperties absent — ArkType by default, Valibot’s object and looseObject |
validation issues, joined by ; | your refinements failed; paths prefixed as field.nested: message |
Decode-time errors
Section titled “Decode-time errors”All DecodeError with an offset.
| Message | Cause |
|---|---|
Expected a Uint8Array, received X | wrong input type; offset 0 |
Unexpected trailing data | bytes remained after a complete value |
Payload was written by a different schema (expected fingerprint XXXXXX) | the schema changed |
| out-of-bounds read | truncated payload |
| non-canonical varint | overlong, e.g. [129, 0] for 1 |
| unsafe integer | a varint beyond the safe integer range |
| invalid UTF-8 | decoding is fatal, not replacing |
| invalid boolean | a byte other than 0 or 1 |
| invalid enum index | past the last member |
| element count exceeds remaining input | a count the payload cannot satisfy |
Handle fingerprint mismatches explicitly in production. In the mismatch test, decoding without a fingerprint produced a wrong value without an error about 27% of the time. See Schema Evolution.
One error that is not a DecodeError
Section titled “One error that is not a DecodeError”A schema nested about 5,900 levels deep can overflow the JavaScript stack and throw RangeError instead of DecodeError. This requires a hostile schema, not only hostile bytes. Limit schema depth if schemas come from untrusted input. See Hostile Input.