{"record":{"id":"2a6bfded4f39dae0","repo":"n8n-io/n8n","slug":"failed-to-spawn-daemon-command-did-not-start","errorCode":null,"errorMessage":"Failed to spawn daemon: `${command}` did not start. See ${args.logPath} for details.","messagePattern":"Failed to spawn daemon: `(.+?)` did not start\\. See (.+?) for details\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/instance-ai/evaluations/computer-use/daemon.ts","lineNumber":221,"sourceCode":"\t\t\t// the UI clicks Connect itself between scenarios. Avoids the manual\n\t\t\t// click each time `browser_disconnect` resets the session at the end\n\t\t\t// of a credential-setup orchestration run.\n\t\t\tenv: { ...process.env, FORCE_COLOR: '0', N8N_EVAL_AUTO_BROWSER_CONNECT: '1' },\n\t\t});\n\n\t\t// `spawn` reports failures asynchronously via 'error' (e.g. ENOENT when the\n\t\t// command isn't on PATH). With a detached/unref'd child, an unhandled\n\t\t// 'error' event would crash the parent. Surface the failure in both the\n\t\t// daemon log and the eval logger so the pairing-poll timeout that follows\n\t\t// has a real cause attached, rather than just timing out silently.\n\t\tchild.once('error', (error: Error) => {\n\t\t\tconst message = `[daemon] spawn failed (${command}): ${error.message}\\n`;\n\t\t\targs.logger.error(`Failed to spawn daemon (${command}): ${error.message}`);\n\t\t\tvoid appendFile(args.logPath, message).catch(() => {});\n\t\t});\n\n\t\tif (child.pid === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to spawn daemon: \\`${command}\\` did not start. See ${args.logPath} for details.`,\n\t\t\t);\n\t\t}\n\t\tchild.unref();\n\t\treturn child.pid;\n\t} finally {\n\t\tawait logFile.close();\n\t}\n}\n","sourceCodeStart":203,"sourceCodeEnd":231,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/instance-ai/evaluations/computer-use/daemon.ts#L203-L231","documentation":"Thrown by `spawnDaemonDetached()` when `spawn(...)` returns a child whose `pid` is `undefined`. Node sets `pid` to undefined when the child could not be spawned at all (most commonly ENOENT — the command doesn't exist on PATH). The function also attaches a one-shot `'error'` listener that writes the underlying spawn error to the daemon log and the eval logger, so the message deliberately points at the log for the real OS-level cause rather than guessing.","triggerScenarios":"`usePublishedDaemon` is true but `npx` is not on PATH (no Node, misconfigured PATH, nvm not loaded in the spawning shell). `usePublishedDaemon` is false but `process.execPath` somehow resolves to a non-existent binary (extremely rare; would indicate a corrupted Node install). On some systems, spawning a detached child with `stdio` piped to a just-opened log fd can fail synchronously if the fd is invalid.","commonSituations":"Running under a process supervisor (systemd, pm2) that doesn't inherit the developer's PATH, so `npx` isn't found. Containerized runs where Node is installed but `npx` isn't symlinked. A typo'd or overridden NODE_OPTIONS / NODE_PATH that breaks spawn. The spawn 'error' event fired with ENOENT and was logged, then the synchronous `child.pid === undefined` check ran immediately after.","solutions":["Open `.eval-output/daemon.log` — the `[daemon] spawn failed (<command>): <error>` line names the exact OS error (usually `spawn npx ENOENT`).","If ENOENT for `npx`: ensure Node/npm is installed and on PATH for the shell launching the eval; for a published-daemon run you can also switch to `--use-published-daemon=false` (the default) which uses `process.execPath` directly and doesn't need npx on PATH.","If ENOENT for the local build: that's a different error (424); confirm the build exists.","If the log shows no spawn-failed line at all, the failure happened before the listener attached — check that the log fd was opened successfully and that `process.execPath` is valid."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  pid = await spawnDaemonDetached(args);\n} catch (e) {\n  if (e instanceof Error && /did not start/.test(e.message)) {\n    const log = await readFile(args.logPath, 'utf-8').catch(() => '(no log)');\n    throw new Error(`${e.message}\\n--- daemon.log ---\\n${log}`);\n  }\n  throw e;\n}","preventionTips":["Ensure `npx` (or `process.execPath`) is resolvable from the spawning shell's PATH — process supervisors often don't inherit the user PATH.","In containers, confirm `npx` exists before relying on `--use-published-daemon`.","Prefer the local-build path (default) which uses `process.execPath` directly and avoids the npx-on-PATH dependency."],"tags":["daemon","computer-use","spawn","enoent","environment","debugging"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}