stablyai/orca · error · Error

Recorded benchmark helper PID changed before signaling

Error message

Recorded benchmark helper PID changed before signaling

What it means

Within signalProcessIdentity, after SIGSTOP'ing the recorded helper, the code re-reads its identity. If sameIdentity fails, the process changed during the stop window — same PID-recycle race as 144 but caught one step later. The function then attempts a SIGCONT recovery before re-throwing.

Source

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

  expectedCommandFragment,
  signal,
  operations = processSignalOperations
) {
  validateDetachedIdentity(identity, expectedCommandFragment)
  const currentIdentity = operations.processIdentity(identity.pid)
  if (!currentIdentity) {
    return false
  }
  if (!sameIdentity(currentIdentity, identity)) {
    throw new Error('Recorded benchmark helper PID now belongs to another process')
  }
  let stopped = false
  try {
    operations.signalProcess(identity.pid, 'SIGSTOP')
    stopped = true
    const stoppedIdentity = operations.processIdentity(identity.pid)
    if (!sameIdentity(stoppedIdentity, identity)) {
      throw new Error('Recorded benchmark helper PID changed before signaling')
    }
    operations.signalProcess(-identity.pgid, signal)
    if (signal !== 'SIGKILL') {
      operations.signalProcess(-identity.pgid, 'SIGCONT')
    }
    stopped = false
    return true
  } catch (error) {
    let resumeError
    if (stopped) {
      try {
        operations.signalProcess(identity.pid, 'SIGCONT')
      } catch (caught) {
        if (caught?.code !== 'ESRCH') {
          resumeError = caught
        }
      }
    }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Treat as an invalid trial — the helper is not reliably controllable; re-spawn it
  2. Stop using SIGSTOP for helpers with handlers that exit on stop; use SIGKILL-only signaling for those
  3. Make test stubs deterministic: processIdentity should return the same object for a given pid until an explicit exit is simulated
  4. Add a processIdentityIsCurrent gate before signaling to fail fast with 144 instead
Defensive patterns

Strategy: try-catch

Try / catch

try {
  signalProcessIdentity(recorded, frag, sig)
} catch (error) {
  if (/changed before signaling/.test(error.message)) {
    killProcessMatchingCommand([frag])
  } else throw error
}

Prevention

When it happens

Trigger: operations.signalProcess(identity.pid, 'SIGSTOP') succeeds, then operations.processIdentity(identity.pid) returns an identity whose pgid or command differs from the recorded one.

Common situations: Helper exited immediately upon SIGSTOP (signal handler called _exit) and the PID was reused before the re-check; or test stubs return inconsistent identities across calls.

Related errors


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