{"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/01e15490f04e29cfefe3896951f43db46994d8ee/skills/terminal-opener/scripts/open-terminal.js#L250-L286","documentation":"launchDetached wraps spawnImpl (child_process.spawn by default) in a try. If spawn throws synchronously — invalid command type, EACCES on the binary, EINVAL options — the error is re-thrown as 'Unable to start <command>: <message>' with the original error attached via { cause }. This is the synchronous spawn-failure path; asynchronous errors go through the child's 'error' event and the onDetachedError callback instead.","triggerScenarios":"spawnImpl(command, args, opts) throws synchronously inside launchDetached. Called from launch() for recover mode (line 293) and for the fallback after a failed mux spawn (line 314).","commonSituations":"wezterm binary present but not executable (EACCES); command argument of the wrong type; a custom injected spawnImpl that throws; ENOENT-style failures surfacing synchronously on some platforms.","solutions":["Inspect error.cause for the original syscall error (EACCES, EINVAL, ENOENT).","Ensure the wezterm binary is executable and on PATH (run --detect first).","If injecting a custom spawnImpl dependency, ensure it returns a ChildProcess and only throws on genuine failures."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  launch(plan);\n} catch (error) {\n  if (error.message.startsWith('Unable to start') && error.cause) {\n    log.error('terminal spawn failed', { code: error.cause.code, message: error.cause.message });\n  }\n  throw error;\n}","preventionTips":["Run with --detect first to confirm the terminal binary is present and executable before --launch.","Inspect error.cause for the underlying syscall error (EACCES, ENOENT, EINVAL).","Ensure the wezterm binary is on PATH and executable in the environment that spawns the script."],"tags":["subprocess","terminal","spawn","launch"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}