n8n-io/n8n · error · Error

Daemon spawned (pid ${pid}) but did not pair within ${String

Error message

Daemon spawned (pid ${pid}) but did not pair within ${String(PAIRING_TIMEOUT_MS / 1000)}s. Check ${logPath} for errors.

What it means

Thrown by `ensureDaemon()` after the daemon process was spawned (a pid was returned) but the gateway status poll never reported `connected` within `PAIRING_TIMEOUT_MS` (90s). The loop polls `client.getGatewayStatus()` every 500ms; if no successful pairing happens in 180 polls, the daemon is considered wedged. The message points at the daemon log file (`.eval-output/daemon.log`) which will contain the daemon's stdout/stderr and usually the real cause.

Source

Thrown at packages/@n8n/instance-ai/evaluations/computer-use/daemon.ts:124

		usePublished,
		logger,
	});
	logger.info(`Daemon spawned (pid ${pid}, log: ${logPath})`);
	logger.info('Daemon will keep running after the eval exits — re-runs will reuse it.');

	const deadline = Date.now() + PAIRING_TIMEOUT_MS;
	while (Date.now() < deadline) {
		await delay(PAIRING_POLL_INTERVAL_MS);
		status = await client.getGatewayStatus();
		if (status.connected && status.directory) {
			logger.info(
				`Daemon paired in ${String(Math.round((PAIRING_TIMEOUT_MS - (deadline - Date.now())) / 1000))}s`,
			);
			return toInfo(status);
		}
	}

	throw new Error(
		`Daemon spawned (pid ${pid}) but did not pair within ${String(PAIRING_TIMEOUT_MS / 1000)}s. ` +
			`Check ${logPath} for errors.`,
	);
}

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------

function toInfo(status: {
	directory: string | null;
	toolCategories: Array<{ name: string; enabled: boolean }>;
}): DaemonInfo {
	return {
		directory: status.directory ?? '',
		enabledCategories: (status.toolCategories ?? []).filter((c) => c.enabled).map((c) => c.name),
	};
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Read `.eval-output/daemon.log` (the path in the error) — the daemon's own stderr will state why it didn't pair (port conflict, token error, missing browser, etc.).
  2. If the log shows a spawn failure or crash, rebuild `@n8n/computer-use` and `@n8n/mcp-browser` and try again.
  3. If the log shows the daemon is healthy but pairing never completes, check the browser extension is installed and n8n is reachable from the daemon's host; verify `--base-url` matches what the daemon was spawned with.
  4. If running on a chronically slow machine, you cannot raise the timeout from the CLI (PAIRING_TIMEOUT_MS is a constant); start the daemon manually beforehand so `ensureDaemon` reuses it instead of spawning.
  5. If a previous wedged daemon is still running, kill it (`pkill -f computer-use`) before re-running so the runner doesn't reuse a stuck process.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const info = await ensureDaemon(opts);
} catch (e) {
  if (e instanceof Error && /did not pair within/.test(e.message)) {
    // read the daemon log for the real cause before retrying
    const log = await readFile(join(opts.evalOutputDir, 'daemon.log'), 'utf-8');
    throw new Error(`${e.message}\n--- daemon.log ---\n${log}`);
  }
  throw e;
}

Prevention

When it happens

Trigger: Daemon started but crashed immediately (the spawn-error handler appended `[daemon] spawn failed (...)` to the log but the process lingered long enough to report a pid). Daemon started but the pairing token was rejected by n8n (clock skew, mismatched baseUrl, expired link token). Daemon started but couldn't reach the browser extension / playwright, so it never reached 'connected'. Network/firewall blocking the daemon's loopback webhook back to n8n.

Common situations: First run on a machine where the browser extension isn't installed/connected. After changing `--base-url` such that the daemon can reach n8n but the browser side can't reach the daemon. After a Node version change that breaks a native dep in `@n8n/mcp-browser`. On a slow CI box where 90s isn't enough (rare — pairing is usually <10s).

Understand the failure class

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/4e29569e865024aa. Report an issue: GitHub.