ruvnet/ruflo · error
ruflo proxy supervisor failed to spawn — no PID returned
Error message
ruflo proxy supervisor failed to spawn — no PID returned
What it means
After spawning the detached supervisor (process.execPath + ['proxy', 'supervise']), Node returned a ChildProcess without a pid. The PID is required to write the pid file, so startBackground() aborts before recording anything. This is a rare spawn-level runtime failure — the supervisor never became observable, not a proxy-level crash.
Solutions
- Retry the start once — transient resource pressure is the most common cause
- Check process limits on the host (`ulimit -u`, container pids.max) and raise them or reduce load
- Inspect the service log file for an immediately-exiting supervisor; free resources and run `ruflo proxy start --service` again
Defensive patterns
Strategy: retry
Validate before calling
import { readFileSync } from 'node:fs';
// Host-level pre-check for hardened Linux environments
try {
const max = readFileSync('/sys/fs/cgroup/pids.max', 'utf8').trim();
if (max !== 'max' && Number(max) < 100) throw new Error('cgroup pids.max too low for the supervisor');
} catch (e) { if (/pids\.max/.test(String(e))) throw e; } // absent file/cgroup: skip Type guard
const isSpawnNoPid = (e: unknown): e is Error => e instanceof Error && /failed to spawn — no PID returned/.test(e.message);
Try / catch
for (let attempt = 1; attempt <= 2; attempt++) {
try {
return await startBackground();
} catch (e) {
if (attempt === 2 || !isSpawnNoPid(e)) throw e;
await new Promise(r => setTimeout(r, 500)); // transient resource pressure
}
} Prevention
- Raise pid limits (RLIMIT_NPROC / cgroup pids.max) in containers before enabling service mode
- Avoid starting the service at peak machine load
- After a no-PID failure, check the service log file for an immediately-exiting child
When it happens
Trigger: spawn() returning a ChildProcess whose pid is undefined — typically resource exhaustion (fork limits, RLIMIT_NPROC, cgroup pids.max) or a broken runtime where the fork result is unavailable to Node.
Common situations: Containers with tight process limits; heavily loaded CI machines; sandboxed environments restricting process creation.
Related errors
- cannot locate the ruflo CLI entrypoint for supervised…
- Meta-Proxy did not return a process id.
- no log file yet — meta-proxy has never been started in…
- Agent with name ' ' already exists
- archive did not contain the expected binary at its root
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/fddff29200b7482e.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/proxy/lifecycle.ts:230
const lockFd = acquireStartLock();
try {
// Re-check under the lock — the dedup above raced a concurrent starter.
const rechecked = getProxyStatus();
if (rechecked.running && rechecked.pid) throw new ProxyAlreadyRunningError(rechecked.pid);
if (rechecked.stalePidFile) clearStalePidFile();
const logFd = fs.openSync(proxyLogFilePath(), 'a');
const cliEntry = process.argv[1];
if (!cliEntry) throw new Error('cannot locate the ruflo CLI entrypoint for supervised service mode');
const child = spawn(process.execPath, [cliEntry, 'proxy', 'supervise'], {
stdio: ['ignore', logFd, logFd],
detached: true,
windowsHide: true,
});
fs.closeSync(logFd); // the child holds its own duplicated fd; safe to close ours
if (!child.pid) throw new Error('ruflo proxy supervisor failed to spawn — no PID returned');
writePidFile(child.pid);
child.unref();
return { pid: child.pid };
} finally {
releaseStartLock(lockFd);
}
}
export interface StopResult {
wasRunning: boolean;
pid: number | null;
}
/** SIGTERM -> 1000ms -> SIGKILL if still alive, mirroring daemon.ts's killBackgroundDaemon. */
export async function stopProxy(): Promise<StopResult> {
const status = getProxyStatus();
if (!status.running || !status.pid) {
if (status.stalePidFile) clearStalePidFile();View on GitHub (pinned to fa13ee4ad6)