{"record":{"id":"71124778a8209df7","repo":"garrytan/gstack","slug":"unknown-command-c-rawname","errorCode":null,"errorMessage":"Unknown command: ${c.rawName}","messagePattern":"Unknown command: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browse/src/meta-commands.ts","lineNumber":697,"sourceCode":"            let result: string;\n            if (WRITE_COMMANDS.has(name)) {\n              if (bm.isWatching()) {\n                result = 'BLOCKED: write commands disabled in watch mode';\n              } else {\n                result = await handleWriteCommand(name, cmdArgs, session, bm);\n              }\n              lastWasWrite = true;\n            } else if (READ_COMMANDS.has(name)) {\n              result = await handleReadCommand(name, cmdArgs, session);\n              if (PAGE_CONTENT_COMMANDS.has(name)) {\n                result = wrapUntrustedContent(result, bm.getCurrentUrl());\n              }\n              lastWasWrite = false;\n            } else if (META_COMMANDS.has(name)) {\n              result = await handleMetaCommand(name, cmdArgs, bm, shutdown, tokenInfo, opts);\n              lastWasWrite = false;\n            } else {\n              throw new Error(`Unknown command: ${c.rawName}`);\n            }\n            results.push(`[${label}] ${result}`);\n          } catch (err: any) {\n            results.push(`[${label}] ERROR: ${err.message}`);\n          }\n        }\n      }\n\n      // Wait for network to settle after write commands before returning\n      if (lastWasWrite) {\n        await bm.getPage().waitForLoadState('networkidle', { timeout: 2000 }).catch(() => {});\n      }\n\n      return results.join('\\n\\n');\n    }\n\n    // ─── Diff ──────────────────────────────────────────\n    case 'diff': {","sourceCodeStart":679,"sourceCodeEnd":715,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/meta-commands.ts#L679-L715","documentation":"In the CLI/fallback dispatch path (when `opts.executeCommand` is not provided), each chain subcommand is routed by checking membership in `WRITE_COMMANDS`, `READ_COMMANDS`, then `META_COMMANDS` (lines 680-697). If the canonical name matches none of these sets, the dispatcher throws `Unknown command`. This path runs only in direct-CLI mode; the server path delegates to `handleCommandInternal` instead.","triggerScenarios":"A chain subcommand whose canonical name is not registered in any of the three command sets — e.g. a typo (`[[\"got\",\"https://x\"]]`), a removed/renamed command, or a command only reachable via server dispatch being run in CLI fallback mode.","commonSituations":"Running `browse chain` from the CLI (no server) with a command name that exists in the server registry but not in the local sets, or after a rename where old scripts still reference the previous name.","solutions":["Check the subcommand spelling and use the canonical name (run via the server for alias normalization).","If the command is real but only registered server-side, invoke chain through the server (which sets `opts.executeCommand`) instead of the CLI fallback.","Consult the command registry (`WRITE_COMMANDS`/`READ_COMMANDS`/`META_COMMANDS`) to confirm the canonical name."],"exampleFix":"// before\nbrowse chain '[[\"got\",\"https://x\"]]'  // typo\n// after\nbrowse chain '[[\"goto\",\"https://x\"]]'","handlingStrategy":"validation","validationCode":"import { READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS, canonicalizeCommand } from './commands';\nconst KNOWN = new Set([...READ_COMMANDS, ...WRITE_COMMANDS, ...META_COMMANDS]);\nconst unknown = chainCmds.filter(c => !KNOWN.has(canonicalizeCommand(c)));\nif (unknown.length) throw new Error(`Unknown chain subcommand(s): ${unknown.join(', ')}`);","typeGuard":"const isKnownCommand = (name: string): boolean =>\n  READ_COMMANDS.has(name) || WRITE_COMMANDS.has(name) || META_COMMANDS.has(name);","tryCatchPattern":"try { await browse.chain(payload); }\ncatch (err) {\n  if (/Unknown command/.test(err.message)) {\n    // surface the bad subcommand to the caller; do NOT silently retry\n  }\n}","preventionTips":["Validate subcommand names against the registry before dispatch.","Route chains through the server (which normalizes aliases) rather than the CLI fallback path.","After renames, grep old command names across calling code."],"tags":["chain","command-dispatch","cli"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}