NousResearch/hermes-agent · warning · LoadoutError
That doesn't look like a ${noun}.
Error message
That doesn't look like a ${noun}. What it means
Thrown by the loadout codec's decode() in apps/desktop/src/lib/loadout.ts:242 when, after stripping ALL whitespace and removing the spec prefix, nothing remains. Share codes are namespaced strings like '<prefix><base64url payload>'; an input consisting only of the prefix (or only whitespace/prefix) is rejected immediately as 'not looking like' the expected thing. This is the first, cheapest parse gate before base64 decoding is attempted.
Source
Thrown at apps/desktop/src/lib/loadout.ts:242
head.uint(spec.version, 8)
head.uint(checksum16(payload), 16)
const headBytes = head.bytes()
const framed = new Uint8Array(headBytes.length + payload.length)
framed.set(headBytes, 0)
framed.set(payload, headBytes.length)
return spec.prefix + toBase64Url(framed)
}
const decode = (code: string): T => {
// Strip ALL whitespace, not just the ends — a pasted code often picks up soft
// wraps / newlines, and base64 decoding chokes on any of it.
const cleaned = code.replace(/\s+/g, '')
const raw = cleaned.startsWith(spec.prefix) ? cleaned.slice(spec.prefix.length) : cleaned
if (!raw) {
throw new Err(`That doesn't look like a ${noun}.`)
}
let framed: Uint8Array
try {
framed = fromBase64Url(raw)
} catch {
throw new Err(`That doesn't look like a ${noun}.`)
}
if (framed.length <= HEAD_BYTES) {
throw new Err(`${Noun} is too short to be valid.`)
}
const head = new BitReader(framed.subarray(0, HEAD_BYTES))
const version = head.uint(8)
const storedSum = head.uint(16)
View on GitHub (pinned to c896c09c42)
Solutions
- Re-copy the full share code from its source and paste without editing.
- Validate non-empty before decode: strip whitespace and the prefix, require at least one remaining character.
- Fix the producer that emitted prefix-only codes (encode() with an empty payload is almost always a bug).
- Show the codec's typed error to the user — the message is intentionally human-readable for paste flows.
Example fix
// before
const set = decode(pasted.trim()) // throws when pasted is prefix-only
// after
const cleaned = pasted.replace(/\s+/g, '')
if (cleaned.length <= PREFIX.length || !cleaned.startsWith(PREFIX)) {
showPasteError('Paste the full share code'); return
}
const set = decode(cleaned) Defensive patterns
Strategy: validation
Validate before calling
function hasPayloadAfterPrefix(code: string, prefix: string): boolean {
const cleaned = code.replace(/\s+/g, '')
return cleaned.length > prefix.length && cleaned.startsWith(prefix)
} Try / catch
try { const v = decode(input) } catch (e) { if (e instanceof Err && /doesn't look like/.test(e.message)) { showPasteError(e.message); return null } throw e } Prevention
- Never call decode on unvalidated paste input — strip whitespace and check for a non-empty suffix first
- Copy codes whole; avoid manual retyping
- Fix producers that emit prefix-only codes
- Prefer the typed Err catch over generic Error handling so paste UX stays friendly
When it happens
Trigger: Pasting just the prefix token ('hermes-skills:' or similar) with no payload; input that is entirely whitespace after cleaning; an empty string passed to decode; prefix repeated with no payload ('PREFIXPREFIX').
Common situations: User pastes a truncated code cut off at a soft wrap; a clipboard manager grabbed only the first line; UI forwarding an empty input field to decode; test fixtures with placeholder codes.
Related errors
- ${Noun} is too short to be valid.
- ${Noun} is version ${version}; this build reads version ${sp
- ${Noun} looks corrupted (checksum mismatch).
- ${Noun} is malformed: ${err.message}
- Branch name is required.
AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14).
Data as JSON: /api/errors/db078d1d5cb85852.
Report an issue: GitHub.