{"record":{"id":"db078d1d5cb85852","repo":"NousResearch/hermes-agent","slug":"that-doesn-t-look-like-a-noun","errorCode":null,"errorMessage":"That doesn't look like a ${noun}.","messagePattern":"That doesn't look like a (.+?)\\.","errorType":"exception","errorClass":"LoadoutError","httpStatus":null,"severity":"warning","filePath":"apps/desktop/src/lib/loadout.ts","lineNumber":242,"sourceCode":"    head.uint(spec.version, 8)\n    head.uint(checksum16(payload), 16)\n    const headBytes = head.bytes()\n\n    const framed = new Uint8Array(headBytes.length + payload.length)\n    framed.set(headBytes, 0)\n    framed.set(payload, headBytes.length)\n\n    return spec.prefix + toBase64Url(framed)\n  }\n\n  const decode = (code: string): T => {\n    // Strip ALL whitespace, not just the ends — a pasted code often picks up soft\n    // wraps / newlines, and base64 decoding chokes on any of it.\n    const cleaned = code.replace(/\\s+/g, '')\n    const raw = cleaned.startsWith(spec.prefix) ? cleaned.slice(spec.prefix.length) : cleaned\n\n    if (!raw) {\n      throw new Err(`That doesn't look like a ${noun}.`)\n    }\n\n    let framed: Uint8Array\n\n    try {\n      framed = fromBase64Url(raw)\n    } catch {\n      throw new Err(`That doesn't look like a ${noun}.`)\n    }\n\n    if (framed.length <= HEAD_BYTES) {\n      throw new Err(`${Noun} is too short to be valid.`)\n    }\n\n    const head = new BitReader(framed.subarray(0, HEAD_BYTES))\n    const version = head.uint(8)\n    const storedSum = head.uint(16)\n","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/NousResearch/hermes-agent/blob/c896c09c42910c584c4c7d2325b58c14713ea42c/apps/desktop/src/lib/loadout.ts#L224-L260","documentation":"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.","triggerScenarios":"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').","commonSituations":"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.","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."],"exampleFix":"// before\nconst set = decode(pasted.trim()) // throws when pasted is prefix-only\n\n// after\nconst cleaned = pasted.replace(/\\s+/g, '')\nif (cleaned.length <= PREFIX.length || !cleaned.startsWith(PREFIX)) {\n  showPasteError('Paste the full share code'); return\n}\nconst set = decode(cleaned)","handlingStrategy":"validation","validationCode":"function hasPayloadAfterPrefix(code: string, prefix: string): boolean {\n  const cleaned = code.replace(/\\s+/g, '')\n  return cleaned.length > prefix.length && cleaned.startsWith(prefix)\n}","typeGuard":null,"tryCatchPattern":"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 }","preventionTips":["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"],"tags":["desktop","loadout","validation","user-input","share-codes"],"backgroundTag":null,"analyzedSha":"c896c09c42910c584c4c7d2325b58c14713ea42c","analyzedAt":"2026-08-14T17:18:01.089Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}