{"record":{"id":"66d428756d5286d2","repo":"affaan-m/ECC","slug":"unable-to-start-command-error-message","errorCode":null,"errorMessage":"Unable to start ${command}: ${error.message}","messagePattern":"Unable to start (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/terminal-opener/scripts/open-terminal.js","lineNumber":268,"sourceCode":"  };\n}\n\nfunction reportDetachedError(error) {\n  process.stderr.write(`Error: ${error.message}\\n`);\n  process.exitCode = 1;\n}\n\nfunction launchDetached(command, args, cwd, spawnImpl, onDetachedError) {\n  let child;\n  try {\n    child = spawnImpl(command, args, {\n      cwd,\n      detached: true,\n      shell: false,\n      stdio: 'ignore',\n    });\n  } catch (error) {\n    throw new Error(`Unable to start ${command}: ${error.message}`, { cause: error });\n  }\n  if (!child || typeof child.unref !== 'function') {\n    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;","sourceCodeStart":250,"sourceCodeEnd":286,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/terminal-opener/scripts/open-terminal.js#L250-L286","documentation":"launchDetached wraps a synchronous spawn failure (child_process.spawn throwing synchronously) into `Unable to start <command>: <reason>` with the original error attached as `cause`. It means the OS/Node refused to even create the terminal process for the resolved terminal command.","triggerScenarios":"spawn() throws synchronously for the detached child — e.g. the terminal binary path does not exist or lacks execute permission, an invalid cwd option, or an options object Node rejects — reaching the catch block around childProcess.spawn.","commonSituations":"Terminal emulator uninstalled or renamed after configuration (e.g. iterm2 config on Linux); cwd directory deleted before launch; running under a restricted environment where spawning detached processes is denied; ENOENT/EPERM/EACCES from the OS.","solutions":["Read error.cause for the underlying errno (ENOENT/EACCES/EPERM) and fix the specific cause.","Verify the terminal command exists: `command -v <terminal>` or run with --detect.","Confirm plan.cwd points to an existing, accessible directory.","Reinstall or reconfigure the terminal emulator named in your settings."],"exampleFix":"// before\nconst child = spawn('kitty', args, { cwd, detached: true }); // kitty not installed\n// after\n// pick an installed terminal (verify with --detect)\nconst child = spawn('gnome-terminal', args, { cwd, detached: true });","handlingStrategy":"try-catch","validationCode":"const { execSync } = require('child_process');\ntry { execSync(`command -v ${terminal}`, { stdio: 'ignore' }); } catch { throw new Error(`Terminal '${terminal}' not found on PATH`); }\nif (!fs.existsSync(cwd)) throw new Error(`cwd does not exist: ${cwd}`);","typeGuard":null,"tryCatchPattern":"try {\n  const result = launch(plan);\n} catch (err) {\n  if (err.message.startsWith('Unable to start')) {\n    console.error(`Spawn failed: ${err.cause ? err.cause.message : err.message}`);\n    if (err.cause?.code === 'ENOENT') console.error('-> terminal binary not found; run --detect to list terminals.');\n    if (err.cause?.code === 'EACCES') console.error('-> binary not executable; fix permissions or pick another terminal.');\n  } else throw err;\n}","preventionTips":["Verify the terminal binary with --detect or `command -v` before launching in automation.","Keep the configured cwd an existing directory; resolve it to an absolute path early.","Log err.cause so the underlying errno (ENOENT/EACCES/EPERM) is visible.","Pin the terminal name per-platform in config rather than one global default."],"tags":["process-spawn","terminal"],"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"}