{"record":{"id":"382b1f2e1e0f1c8a","repo":"affaan-m/ECC","slug":"terminal-process-did-not-start-correctly","errorCode":null,"errorMessage":"Terminal process did not start correctly.","messagePattern":"Terminal process did not start correctly\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skills/terminal-opener/scripts/open-terminal.js","lineNumber":271,"sourceCode":"function 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;\n  const capability = detectTerminalCapability(plan, spawnSyncImpl);\n  if (!capability.available) {\n    throw new Error(`${capability.reason}: ${capability.action}`);","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/skills/terminal-opener/scripts/open-terminal.js#L253-L289","documentation":"launchDetached throws this when the value returned by spawn() is not a usable ChildProcess (missing unref), meaning Node did not produce a real detached process handle. This is an internal invariant check that the process object is malformed rather than a spawn failure.","triggerScenarios":"A dependency-injected/spawned implementation (dependencies.spawn) returns null, undefined, or an object lacking unref — e.g. a test stub or mocked spawn — after the try/catch around the real spawn succeeded.","commonSituations":"Custom dependency injection where a fake spawn returns a plain object; monkey-patching child_process.spawn in tests; unusual Node runtimes/embeddings whose spawn return differs from the documented ChildProcess API.","solutions":["Ensure the spawn implementation passed via dependencies.spawn returns a genuine child_process.ChildProcess (or stub with unref/once).","Update the test mock to `return Object.assign(new EventEmitter(), { unref() {} })`.","Remove any monkey-patching of child_process.spawn that alters its return value in production code."],"exampleFix":"// before\nconst fakeSpawn = () => null;\nlaunch(plan, { spawn: fakeSpawn });\n// after\nconst fakeSpawn = () => Object.assign(new EventEmitter(), { unref() {} });\nlaunch(plan, { spawn: fakeSpawn });","handlingStrategy":"type-guard","validationCode":"const spawnImpl = dependencies.spawn || require('child_process').spawn;\nif (typeof spawnImpl !== 'function') throw new Error('dependencies.spawn must be a function');","typeGuard":"function isChildProcess(c) {\n  return !!c && typeof c.unref === 'function' && typeof c.once === 'function';\n}","tryCatchPattern":"try {\n  launch(plan, { spawn: mySpawn });\n} catch (err) {\n  if (err.message === 'Terminal process did not start correctly.') {\n    console.error('spawn dependency returned a non-ChildProcess; fix the stub/mock.');\n  } else throw err;\n}","preventionTips":["Make test doubles of spawn return objects exposing unref() and once() (EventEmitter-based).","Type injected spawn as returning child_process.ChildProcess so TS catches bad stubs.","Avoid monkey-patching child_process.spawn in production paths."],"tags":["process-spawn","invariant"],"backgroundTag":"internal-invariant-violation","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"}