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

  1. Re-copy the full share code from its source and paste without editing.
  2. Validate non-empty before decode: strip whitespace and the prefix, require at least one remaining character.
  3. Fix the producer that emitted prefix-only codes (encode() with an empty payload is almost always a bug).
  4. 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

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


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/db078d1d5cb85852. Report an issue: GitHub.