{"record":{"id":"0c1f3ff95d4776b4","repo":"garrytan/gstack","slug":"skill-command-requires-daemonport-in-metacommandop","errorCode":null,"errorMessage":"skill command requires daemonPort in MetaCommandOpts (server bug)","messagePattern":"skill command requires daemonPort in MetaCommandOpts \\(server bug\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"browse/src/meta-commands.ts","lineNumber":1152,"sourceCode":"          breadcrumbs,\n          headings,\n          interactive,\n          textBlocks,\n          totalWords,\n        };\n      });\n\n      return JSON.stringify(data, null, 2);\n    }\n\n    case 'domain-skill': {\n      return await handleDomainSkillCommand(args, bm);\n    }\n\n    case 'skill': {\n      const port = opts?.daemonPort;\n      if (port === undefined) {\n        throw new Error('skill command requires daemonPort in MetaCommandOpts (server bug)');\n      }\n      return await handleSkillCommand(args, { port });\n    }\n\n    case 'cdp': {\n      // Lazy import — cdp-bridge introduces module deps we don't want loaded\n      // for projects that never use the CDP escape hatch.\n      const { handleCdpCommand } = await import('./cdp-commands');\n      return await handleCdpCommand(args, bm);\n    }\n\n    case 'memory': {\n      // Lazy import — pulls in cdp-bridge + memory-snapshot + buffer accessors\n      // that aren't useful for projects that never run the diagnostic.\n      const { handleMemoryCommand } = await import('./memory-command');\n      return await handleMemoryCommand(args, bm);\n    }\n","sourceCodeStart":1134,"sourceCodeEnd":1170,"githubUrl":"https://github.com/garrytan/gstack/blob/94993f74012782fd94416dd44b8314f6363a13a4/browse/src/meta-commands.ts#L1134-L1170","documentation":"The `skill` meta-command needs a daemon port to reach the local skill daemon, read from `opts.daemonPort` (lines 1149-1153). If the caller (CLI or test harness) did not populate `MetaCommandOpts.daemonPort`, the command refuses to run rather than dialing a default port. The message explicitly labels this a server bug because opts should always be populated by the server.","triggerScenarios":"Invoking `handleMetaCommand('skill', ...)` without passing `opts.daemonPort`, or the server failing to inject its listening port into the MetaCommandOpts.","commonSituations":"Test harnesses constructing `MetaCommandOpts` by hand; a refactor that stopped forwarding `daemonPort` from the server; CLI direct-dispatch path that bypasses server wiring.","solutions":["Ensure the server sets `opts.daemonPort` to its listening port when dispatching meta commands.","If calling from tests, populate `opts: { daemonPort: <port> }` explicitly.","If no daemon is running, start it (or use `domain-skill` instead, which doesn't need the port)."],"exampleFix":"// before\nawait handleMetaCommand('skill', args, bm, shutdown, tokenInfo, { executeCommand });\n// after\nawait handleMetaCommand('skill', args, bm, shutdown, tokenInfo, { executeCommand, daemonPort: 7777 });","handlingStrategy":"validation","validationCode":"if (opts?.daemonPort === undefined) {\n  throw new Error('Cannot dispatch skill command: daemonPort missing from MetaCommandOpts');\n}\nawait handleMetaCommand('skill', args, bm, shutdown, tokenInfo, opts);","typeGuard":"const hasDaemonPort = (o: MetaCommandOpts | undefined): o is MetaCommandOpts & { daemonPort: number } =>\n  typeof o?.daemonPort === 'number';","tryCatchPattern":null,"preventionTips":["Centralize MetaCommandOpts construction in the server and assert daemonPort is set.","In tests, always populate `opts.daemonPort` — treat it as required for `skill`.","Unit-test the opts builder to fail fast if daemonPort is omitted."],"tags":["skill","configuration","server-bug","daemon"],"backgroundTag":null,"analyzedSha":"94993f74012782fd94416dd44b8314f6363a13a4","analyzedAt":"2026-08-12T04:06:23.140Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}