ruvnet/ruflo · error
Competing Meta-Proxy pid ${current.pid} won the port with ve
Error message
Competing Meta-Proxy pid ${current.pid} won the port with version ${current.version}. What it means
launchAndVerify() polls the effective proxy after launching the new binary, expecting the probe to return the pid it just started with the expected version and executable. If the probe instead returns a different pid, another daemon won the port race; the library kills its own (portless) child and throws, reporting the competing pid and version.
Source
Thrown at v3/@claude-flow/cli/src/proxy/activation.ts:144
const log = fs.openSync(proxyLogFilePath(), 'a', 0o600);
try {
const child = spawn(binary, [], { detached: true, stdio: ['ignore', log, log], windowsHide: true });
if (!child.pid) throw new Error('Meta-Proxy did not return a process id.');
child.unref();
fs.writeFileSync(proxyPidFilePath(), `${child.pid}\n`, { mode: 0o600 });
return child.pid;
} finally { fs.closeSync(log); }
}
async function launchAndVerify(binary: string, version: string, wait: Wait): Promise<EffectiveProxy> {
const pid = launch(binary);
for (let attempt = 0; attempt < 100; attempt++) {
await wait(50);
const current = await probeEffectiveProxy();
if (current?.pid === pid && current.version === version && path.resolve(current.executable) === path.resolve(binary)) return current;
if (current && current.pid !== pid) {
try { process.kill(pid, 'SIGTERM'); } catch { /* already exited */ }
throw new Error(`Competing Meta-Proxy pid ${current.pid} won the port with version ${current.version}.`);
}
}
try { process.kill(pid, 'SIGTERM'); } catch { /* already exited */ }
throw new Error(`Meta-Proxy v${version} did not become the effective daemon.`);
}
export async function installAndActivateProxy(version: string, log?: (line: string) => void): Promise<InstallResult & { pid: number }> {
const wait = waitNormally;
const binary = proxyBinaryPath();
const manifest = proxyInstallManifestPath();
const binaryBackup = `${binary}.rollback`;
const manifestBackup = `${manifest}.rollback`;
let release: (() => void) | null = null;
let prior: EffectiveProxy | null = null;
try {
release = await acquireProxyInstallLease(wait);
prior = await stopEffective(wait);
fs.rmSync(binaryBackup, { force: true });View on GitHub (pinned to 29f048fc3b)
Solutions
- Ensure only one activation runs at a time — the install lease helps, but don't start daemons manually in parallel
- Stop any service manager unit that respawns meta-proxy, run the install, then re-enable it
- Find and stop the competing daemon (pid shown in the message), then retry installAndActivateProxy
- Re-run the activation after a few seconds; if it recurs, check the proxy log and port usage (lsof -i :11435) to find who keeps binding
Example fix
// before: respawn racing the upgrade [program:meta-proxy] autorestart=true // after # supervisorctl stop meta-proxy # npx ruflo proxy install --version 1.2.3 # supervisorctl start meta-proxy
Defensive patterns
Strategy: retry
Validate before calling
// Before activating, make sure no other activation/daemon is mid-start
const existing = await probeEffectiveProxy();
if (existing) console.log(`Existing proxy: pid ${existing.pid} v${existing.version} (${existing.executable}) — stop it first`); Type guard
null
Try / catch
try {
await installAndActivateProxy(version);
} catch (e) {
if (e instanceof Error && e.message.includes('won the port')) {
await new Promise(r => setTimeout(r, 10_000));
await installAndActivateProxy(version); // competing transient daemon usually exits
} else throw e;
} Prevention
- Run only one activation at a time (the install lease doesn't cover manual daemon starts)
- Stop any supervisor unit for meta-proxy during upgrades, restart it afterwards
- Don't manually launch meta-proxy in parallel with CLI-driven activation
- In CI, dedicate one job to proxy installation
When it happens
Trigger: installAndActivateProxy() or effective() → launchAndVerify(): while waiting up to 5s for the freshly spawned daemon to bind, another meta-proxy process (started concurrently, or respawned by a supervisor from the still-installed old binary) grabbed the port first.
Common situations: Two terminals/CI jobs activating the proxy at once; systemd restarting the previous daemon just after it was stopped; an old detached meta-proxy that hadn't fully exited when the new one launched; auto-update tooling launching its own instance.
Related errors
- Meta-Proxy port owner pid ${owner.pid} is not a recognized R
- Issue ${input.issueId} is already claimed by ${issue.claimed
- swarm state is busy; retry the outcome update
- meta-proxy is not installed. Run: ruflo proxy install
- meta-proxy is already running (pid ${pid}). Stop it first wi
AI-assisted analysis of ruvnet/ruflo@29f048fc3b (2026-09-01).
Data as JSON: /api/errors/96d53b8a90c9aeeb.
Report an issue: GitHub.