NousResearch/hermes-agent · warning · LoadoutError
${Noun} is malformed: ${err.message}
Error message
${Noun} is malformed: ${err.message} What it means
Thrown by the loadout codec's decode() in apps/desktop/src/lib/loadout.ts:274 when the payload passes version and checksum but fails during inflation (inflateSync) or schema reading (spec.read over BitReader) — the exception's message is appended as '<Noun> is malformed: <reason>'. This catches payloads that are structurally intact per the frame but semantically broken: invalid DEFLATE streams, bit-reads running past the end ('loadout truncated' RangeError gets wrapped here), or schema-level constraint violations inside spec.read.
Source
Thrown at apps/desktop/src/lib/loadout.ts:274
const head = new BitReader(framed.subarray(0, HEAD_BYTES))
const version = head.uint(8)
const storedSum = head.uint(16)
if (version !== spec.version) {
throw new Err(`${Noun} is version ${version}; this build reads version ${spec.version}.`)
}
const payload = framed.subarray(HEAD_BYTES)
if (checksum16(payload) !== storedSum) {
throw new Err(`${Noun} looks corrupted (checksum mismatch).`)
}
try {
return spec.read(new BitReader(inflateSync(payload)))
} catch (err) {
throw new Err(err instanceof Error ? `${Noun} is malformed: ${err.message}` : `${Noun} is malformed.`)
}
}
return { decode, encode }
}
View on GitHub (pinned to c896c09c42)
Solutions
- Read the appended inner message — it identifies whether inflation or a specific schema read failed and usually names the field.
- Round-trip test encode()->decode() for every spec change; a malformed-code error from your own producer is a writer/reader asymmetry bug.
- Ensure spec.read validates its own invariants (throw with a descriptive message) so this error is precise.
- For user-pasted codes, request a fresh code; this stage means the bytes are self-consistent but wrong-shaped.
Example fix
// before — read consumes more than write emits (surfaces as 'malformed: loadout truncated')
write: (w, v) => { w.str(v.name) }
read: r => ({ name: r.str(), extra: r.uint(3) }) // extra never written
// after — symmetric schema
write: (w, v) => { w.str(v.name); w.uint(v.extra ?? 0, 3) }
read: r => ({ name: r.str(), extra: r.uint(3) }) Defensive patterns
Strategy: try-catch
Try / catch
try {
return spec.read(new BitReader(inflateSync(payload)))
} catch (err) {
throw new Err(err instanceof Error ? `${Noun} is malformed: ${err.message}` : `${Noun} is malformed.`)
}
// callers: catch (e) { if (e instanceof Err && /malformed/.test(e.message)) requestFreshCode() } Prevention
- Log the inner message — it pinpoints the failing schema read
- Throw descriptive errors from spec.read's own validation so wrapped messages are actionable
- Round-trip test encode/decode for every schema edit
- Malformed-after-checksum usually means a buggy producer build — collect the code's origin before regenerating
When it happens
Trigger: spec.read throwing its own validation errors (e.g. unknown enum id, out-of-range index); BitReader running off the end because read/write schemas disagree at the current version; inflateSync failing on a payload that checksummed correctly but was produced by a buggy writer.
Common situations: A producer bug writing fewer bits than read consumes while still bumping neither version nor catching the mismatch; schema changes shipped with a version bump but an asymmetric read; codes generated by experimental builds.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- loadout truncated
- That doesn't look like a ${noun}.
- ${Noun} is too short to be valid.
- ${Noun} is version ${version}; this build reads version ${sp
- Branch name is required.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/391e57c81692e3c9.
Report an issue: GitHub.