stablyai/orca · error · Error
Helper did not exit after graceful owner close
Error message
Helper did not exit after graceful owner close
What it means
After the sidecar exits (118 passed), the helper — spawned as a child of the sidecar — must also exit within PROCESS_EXIT_TIMEOUT_MS. waitForProcessExit returning null means the helper outlived its owner, i.e. the owner-loss/orphan behavior this benchmark exists to catch. This is the core regression signal for helper owner-loss handling.
Source
Thrown at config/scripts/macos-computer-helper-owner-loss-benchmark.mjs:317
totalMs,
requestsPerSecond: (ACTIVE_REQUEST_COUNT * 1_000) / totalMs,
medianLatencyMs: median(latencies),
p95LatencyMs: percentile(latencies, 0.95),
maxLatencyMs: Math.max(...latencies)
}
}
async function verifyGracefulClose() {
const { sidecar, helper } = await startAuthenticatedSession()
try {
const startedAt = performance.now()
sidecar.child.disconnect()
if (!(await waitForChildExit(sidecar.child, PROCESS_EXIT_TIMEOUT_MS))) {
throw new Error('Sidecar did not exit after graceful IPC close')
}
const helperExitMs = await waitForProcessExit(helper, PROCESS_EXIT_TIMEOUT_MS)
if (helperExitMs === null) {
throw new Error('Helper did not exit after graceful owner close')
}
return Math.round(performance.now() - startedAt)
} finally {
sidecar.child.kill('SIGKILL')
await stopProcess(helper)
}
}
async function runInternalTrial(expectation) {
let sidecar
let helper
let invalidPeer
let invalidPeerRejected = false
try {
const session = await startAuthenticatedSession()
sidecar = session.sidecar
helper = session.helper
const authenticatedAt = performance.now()View on GitHub (pinned to 1136503c6a)
Solutions
- Confirm the helper's owner-loss mechanism (parent-pid monitor / pipe-to-parent EOF) is installed and firing.
- Raise PROCESS_EXIT_TIMEOUT_MS only after verifying the helper does exit eventually (a slow but correct detector).
- Check for a regression where the helper's signal handler was removed or its parent-pid capture broke.
- Reproduce standalone: spawn sidecar, kill it, observe whether the helper pid disappears.
Example fix
// before
const helperExitMs = await waitForProcessExit(helper, PROCESS_EXIT_TIMEOUT_MS)
if (helperExitMs === null) {
throw new Error('Helper did not exit after graceful owner close')
}
// after
const helperExitMs = await waitForProcessExit(helper, PROCESS_EXIT_TIMEOUT_MS)
if (helperExitMs === null) {
throw new Error(`Helper pid=${helper.pid} did not exit after graceful owner close within ${PROCESS_EXIT_TIMEOUT_MS}ms`)
} Defensive patterns
Strategy: retry
Validate before calling
const ms = await waitForProcessExit(helper, PROCESS_EXIT_TIMEOUT_MS)
if (ms === null) {
throw new Error(`Helper pid=${helper.pid} orphaned after owner exit within ${PROCESS_EXIT_TIMEOUT_MS}ms`)
} Type guard
const isOrphanedHelper = (ms) => ms === null
Try / catch
try {
await verifyGracefulClose()
} catch (e) {
if (/Helper did not exit/.test(e.message)) { /* this is the regression under test — do not silently retry; report and kill */ helper.pid && process.kill(helper.pid, 'SIGKILL'); throw e }
throw e
} Prevention
- Ensure the helper installs an owner-loss watch (parent-pid poll / pipe-EOF) at startup.
- Reproduce standalone (spawn sidecar, kill it, watch helper pid) before bisecting.
- Treat this failure as a real regression, not transient — do not paper over with retries.
When it happens
Trigger: The helper does not monitor its owner (parent pid) and so keeps running as an orphan after the sidecar dies, or its owner-loss detector is too slow and exceeds the timeout.
Common situations: A regression removing/disabling the helper's parent-death watch (e.g. prctl PR_SET_PDEATHSIG on macOS equivalent, or pidfd/poll), the helper blocked in a syscall that ignores the signal, or a slower machine making the detector miss the window.
Related errors
- Could not find helper owned by sidecar ${sidecarPid}
- Sidecar did not exit after graceful IPC close
- Could not read watchdog child RSS for PID ${pid}
- Could not read physical footprint for PIDs ${pids.join(', ')
- Could not read CPU time for PID ${pid}
AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12).
Data as JSON: /api/errors/23bb83bf5e39ff55.
Report an issue: GitHub.