{"record":{"id":"aa4ea6d77a89204b","repo":"ruvnet/ruflo","slug":"stale-meta-proxy-pid-owner-pid-did-not-stop","errorCode":null,"errorMessage":"Stale Meta-Proxy pid ${owner.pid} did not stop.","messagePattern":"Stale Meta-Proxy pid (.+?) did not stop\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/proxy/activation.ts","lineNumber":121,"sourceCode":"      await wait(50);\n    }\n  }\n  throw new Error('Another Ruflo/MetaHarness installer still owns the Meta-Proxy install lease.');\n}\n\nasync function stopEffective(wait: Wait): Promise<EffectiveProxy | null> {\n  const owner = await probeEffectiveProxy();\n  if (!owner) return null;\n  if (!isSupportedOwner(owner.executable, process.platform)) {\n    throw new Error(`Meta-Proxy port owner pid ${owner.pid} is not a recognized Ruflo/MetaHarness binary; refusing to signal it.`);\n  }\n  process.kill(owner.pid, 'SIGTERM');\n  for (let attempt = 0; attempt < 40; attempt++) {\n    await wait(50);\n    const current = await probeEffectiveProxy();\n    if (!current || current.pid !== owner.pid) return owner;\n  }\n  throw new Error(`Stale Meta-Proxy pid ${owner.pid} did not stop.`);\n}\n\nfunction launch(binary: string): number {\n  fs.mkdirSync(path.dirname(proxyLogFilePath()), { recursive: true, mode: 0o700 });\n  const log = fs.openSync(proxyLogFilePath(), 'a', 0o600);\n  try {\n    const child = spawn(binary, [], { detached: true, stdio: ['ignore', log, log], windowsHide: true });\n    if (!child.pid) throw new Error('Meta-Proxy did not return a process id.');\n    child.unref();\n    fs.writeFileSync(proxyPidFilePath(), `${child.pid}\\n`, { mode: 0o600 });\n    return child.pid;\n  } finally { fs.closeSync(log); }\n}\n\nasync function launchAndVerify(binary: string, version: string, wait: Wait): Promise<EffectiveProxy> {\n  const pid = launch(binary);\n  for (let attempt = 0; attempt < 100; attempt++) {\n    await wait(50);","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/ruvnet/ruflo/blob/29f048fc3b556f857cf2b126d2a84c19d2daa0d0/v3/@claude-flow/cli/src/proxy/activation.ts#L103-L139","documentation":"After sending SIGTERM to the recognized daemon on the proxy port, stopEffective() polls up to 40 times at 50ms (2s total) waiting for it to exit. If the process still holds the port after that window, the library gives up and throws rather than proceeding with an upgrade against a still-running old daemon.","triggerScenarios":"installAndActivateProxy() → stopEffective(): the old meta-proxy received SIGTERM but did not exit within ~2 seconds — typically because it is hung, stuck in uninterruptible I/O, ignoring SIGTERM, blocked shutting down active connections, or running under a supervisor that restarts it faster than the poll window.","commonSituations":"The daemon is wedged after a system suspend or heavy load; a systemd/launchd/supervisord unit immediately respawns meta-proxy; the process is in D-state on a stuck mount; very slow disks delay graceful shutdown.","solutions":["Wait a few seconds and retry installAndActivateProxy — transient slow shutdown often resolves","Check the daemon log (proxyLogFilePath()) for shutdown errors and kill the process manually if it is wedged: kill <pid>, then kill -9 <pid> if needed","If a service manager respawns the daemon, stop/disable that unit (systemctl stop/disable or supervisorctl stop) before running the CLI install","Reboot or clean up zombie/stuck processes if the pid is in uninterruptible sleep (D state)"],"exampleFix":"// before: supervisor auto-restarts meta-proxy during upgrade\n[program:meta-proxy]\nautorestart=true\n// after: stop it before upgrading\n# supervisorctl stop meta-proxy && npx ruflo proxy install ...","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  await installAndActivateProxy(version);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('did not stop')) {\n    await new Promise(r => setTimeout(r, 5_000));\n    await installAndActivateProxy(version); // one retry after slow shutdown settles\n  } else throw e;\n}","preventionTips":["Avoid supervisors with instant autorestart managing meta-proxy during upgrades","Monitor daemon health; a hung meta-proxy should be restarted before attempting upgrades","Check the proxy log after any kill/upgrade for shutdown errors","On flaky machines, stop the daemon manually (and verify it exited) before installing"],"tags":["process","shutdown","timeout","proxy"],"backgroundTag":"process-did-not-stop","analyzedSha":"29f048fc3b556f857cf2b126d2a84c19d2daa0d0","analyzedAt":"2026-09-01T11:37:30.251Z","contentChangedAt":"2026-09-01T11:37:30.251Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}