stablyai/orca · error · Error

Recorded benchmark helper ${identity.pid} did not exit

Error message

Recorded benchmark helper ${identity.pid} did not exit

What it means

waitForIdentityExit polls processIdentityIsCurrent every 25ms (PROCESS_POLL_MS) for up to 2s (PROCESS_EXIT_TIMEOUT_MS) using a synchronous Atomics.wait loop. If the process identity still matches after the deadline, the process did not exit and the error fires.

Source

Thrown at config/scripts/macos-computer-helper-owner-loss-processes.mjs:148

    .split('\n')
    .map((line) => line.trim().match(/^(\d+)\s+(\d+)\s+(.+)$/))
    .filter(Boolean)
    .map((match) => ({
      pid: Number(match[1]),
      pgid: Number(match[2]),
      command: match[3]
    }))
}

function waitForIdentityExit(identity) {
  const deadline = Date.now() + PROCESS_EXIT_TIMEOUT_MS
  while (Date.now() < deadline) {
    if (!processIdentityIsCurrent(identity)) {
      return true
    }
    sleepSync(PROCESS_POLL_MS)
  }
  throw new Error(`Recorded benchmark helper ${identity.pid} did not exit`)
}

export function spawnBenchmarkProcess(executable, args, options) {
  return spawnSync(executable, args, {
    ...options,
    detached: true,
    killSignal: 'SIGKILL'
  })
}

export function runBenchmarkCleanupStages(stages) {
  const errors = []
  for (const stage of stages) {
    try {
      stage()
    } catch (error) {
      errors.push(error)
    }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Check the process state with `ps -o pid,stat,command -p <pid>` — D state means uninterruptible I/O
  2. Verify the parent process is alive and reaping zombies (kill the parent if it's stuck)
  3. Confirm the signal was sent to the correct PID/pgid — check for permission errors in the kill call
  4. If the process legitimately needs more time, consider increasing PROCESS_EXIT_TIMEOUT_MS (but investigate the root cause first)

Example fix

// before: fixed 2s timeout may be too short for D-state processes
const PROCESS_EXIT_TIMEOUT_MS = 2_000

// after: escalate signal and extend deadline for stubborn processes
function waitForIdentityExit(identity, timeoutMs = 5_000) {
  const deadline = Date.now() + timeoutMs
  while (Date.now() < deadline) {
    if (!processIdentityIsCurrent(identity)) return true
    sleepSync(PROCESS_POLL_MS)
  }
  throw new Error(`Recorded benchmark helper ${identity.pid} did not exit`)
}
Defensive patterns

Strategy: retry

Validate before calling

// Check process state before waiting — D-state processes cannot be killed
function canExitFast(identity) {
  const identity0 = processIdentity(identity.pid)
  if (!identity0) return true
  const stat = execFileSync('ps', ['-o', 'stat=', '-p', String(identity.pid)], { encoding: 'utf8' }).trim()
  return !stat.includes('D') // D = uninterruptible sleep
}

Try / catch

try {
  waitForIdentityExit(identity)
} catch (error) {
  if (error.message.includes('did not exit')) {
    // escalate: verify SIGKILL was delivered, check for D state
    const stat = execFileSync('ps', ['-o', 'stat=', '-p', String(identity.pid)], { encoding: 'utf8' }).trim()
    if (stat.includes('D')) {
      console.warn('Process in uninterruptible sleep — cannot be killed until I/O completes')
    }
  }
  throw error
}

Prevention

When it happens

Trigger: After sending SIGKILL (or a signal that was ignored), the helper process is still alive after 2s. Causes: process stuck in uninterruptible sleep (D state, waiting on I/O); zombie not reaped by parent; signal was not delivered due to permission issues; the process group signal (-pgid) did not reach the target.

Common situations: Helper is blocked on a filesystem operation in D state; the parent (Electron) is not reaping the zombie; SIGKILL sent to the wrong pgid; macOS App Nap or suspension preventing signal delivery.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/29883be5cb827970. Report an issue: GitHub.