{"record":{"id":"d22388ab673f4a24","repo":"affaan-m/ECC","slug":"capability-reason-capability-action","errorCode":null,"errorMessage":"${capability.reason}: ${capability.action}","messagePattern":"\\$\\{capability\\.reason\\}: \\$\\{capability\\.action\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/terminal-opener/scripts/open-terminal.js","lineNumber":289,"sourceCode":"    throw new Error('Terminal process did not start correctly.');\n  }\n  if (typeof child.once === 'function') {\n    child.once('error', error => {\n      onDetachedError(\n        new Error(`Unable to start ${command}: ${error.message}`, { cause: error })\n      );\n    });\n  }\n  child.unref();\n}\n\nfunction launch(plan, dependencies = {}) {\n  const spawnSyncImpl = dependencies.spawnSync || childProcess.spawnSync;\n  const spawnImpl = dependencies.spawn || childProcess.spawn;\n  const onDetachedError = dependencies.onDetachedError || reportDetachedError;\n  const capability = detectTerminalCapability(plan, spawnSyncImpl);\n  if (!capability.available) {\n    throw new Error(`${capability.reason}: ${capability.action}`);\n  }\n\n  if (plan.launchMode === 'recover') {\n    launchDetached(plan.command, plan.args, plan.cwd, spawnImpl, onDetachedError);\n    return { strategy: 'detached-recover', capability };\n  }\n\n  const muxResult = spawnSyncImpl(plan.command, plan.args, {\n    cwd: plan.cwd,\n    encoding: 'utf8',\n    killSignal: SPAWN_KILL_SIGNAL,\n    shell: false,\n    timeout: SYNC_TIMEOUT_MS,\n  });\n  if (!muxResult.error && muxResult.status === 0) {\n    return { strategy: 'mux', capability };\n  }\n","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/terminal-opener/scripts/open-terminal.js#L271-L307","documentation":"launch checks detectTerminalCapability(plan, spawnSync) before doing anything; when the detected terminal is not available, it throws `<reason>: <action>` — the reason explains why (binary missing, version too old) and the action tells the user what to do (install/configure another terminal).","triggerScenarios":"Calling launch() (directly or via the CLI without --dry-run) when detectTerminalCapability returns { available: false } — typically because `spawnSync(command, ['--version'])` fails: terminal not installed, not on PATH, or unsupported flag set.","commonSituations":"Configured terminal (e.g. 'kitty', 'wezterm') not installed on the machine; running on WSL/SSH headless where no terminal emulator exists; PATH differs in CI vs interactive shell so the binary isn't found; stale config pointing at an old binary name.","solutions":["Read the thrown reason/action text and install the suggested terminal or switch `terminal` in the tool's settings to an installed one.","Run `open-terminal.js --detect` to see which terminals are available on this machine.","Fix PATH so the terminal binary is resolvable (e.g. add its install dir in CI).","Use --dry-run during setup to validate the plan without requiring the binary."],"exampleFix":"// before\n// config: \"terminal\": \"alacritty\"  (not installed)\nlaunch(plan); // throws 'alacritty not found: install alacritty or ...'\n// after\n// config: \"terminal\": \"gnome-terminal\"  (detected as available)\nlaunch(plan);","handlingStrategy":"fallback","validationCode":"const detected = JSON.parse(execSync('node open-terminal.js --detect --json').toString());\nif (!detected.some(t => t.name === config.terminal && t.available)) {\n  config.terminal = detected.find(t => t.available)?.name;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const result = launch(plan);\n} catch (err) {\n  if (/not available|not found|not installed/i.test(err.message)) {\n    console.error(`Terminal unavailable: ${err.message}\\nRun --detect to list installed terminals, or install the suggested one.`);\n  } else throw err;\n}","preventionTips":["Run --detect during setup and store an available terminal in config.","Use --dry-run to validate the plan without needing the binary present.","In CI/headless environments, expect no terminal emulator and skip launching rather than failing.","Keep PATH consistent between interactive shells and automation."],"tags":["terminal","environment","capability-check"],"backgroundTag":"command-not-found","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}