n8n-io/n8n · error · Error
Failed to spawn daemon: `${command}` did not start. See ${ar
Error message
Failed to spawn daemon: `${command}` did not start. See ${args.logPath} for details. What it means
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.
Source
Thrown at packages/@n8n/instance-ai/evaluations/computer-use/daemon.ts:221
// the UI clicks Connect itself between scenarios. Avoids the manual
// click each time `browser_disconnect` resets the session at the end
// of a credential-setup orchestration run.
env: { ...process.env, FORCE_COLOR: '0', N8N_EVAL_AUTO_BROWSER_CONNECT: '1' },
});
// `spawn` reports failures asynchronously via 'error' (e.g. ENOENT when the
// command isn't on PATH). With a detached/unref'd child, an unhandled
// 'error' event would crash the parent. Surface the failure in both the
// daemon log and the eval logger so the pairing-poll timeout that follows
// has a real cause attached, rather than just timing out silently.
child.once('error', (error: Error) => {
const message = `[daemon] spawn failed (${command}): ${error.message}\n`;
args.logger.error(`Failed to spawn daemon (${command}): ${error.message}`);
void appendFile(args.logPath, message).catch(() => {});
});
if (child.pid === undefined) {
throw new Error(
`Failed to spawn daemon: \`${command}\` did not start. See ${args.logPath} for details.`,
);
}
child.unref();
return child.pid;
} finally {
await logFile.close();
}
}
View on GitHub (pinned to 5ac6606e81)
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.
Defensive patterns
Strategy: try-catch
Try / catch
try {
pid = await spawnDaemonDetached(args);
} catch (e) {
if (e instanceof Error && /did not start/.test(e.message)) {
const log = await readFile(args.logPath, 'utf-8').catch(() => '(no log)');
throw new Error(`${e.message}\n--- daemon.log ---\n${log}`);
}
throw e;
} Prevention
- 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.
When it happens
Trigger: `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.
Common situations: 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.
Related errors
- Daemon spawned (pid ${pid}) but did not pair within ${String
- No computer-use daemon is paired with this n8n instance. Ei
- Local computer-use build not found at ${LOCAL_COMPUTER_USE_C
- NODE_TYPE_NOT_FOUND
- Gateway rejected token: ${status} ${body}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/2a6bfded4f39dae0.
Report an issue: GitHub.