{"record":{"id":"02c14172ad0514c4","repo":"stablyai/orca","slug":"benchmark-process-group-recovery-failed-before-val","errorCode":null,"errorMessage":"Benchmark process group recovery failed before validation","messagePattern":"Benchmark process group recovery failed before validation","errorType":"exception","errorClass":"AggregateError","httpStatus":null,"severity":"error","filePath":"config/scripts/macos-computer-helper-owner-loss-processes.mjs","lineNumber":238,"sourceCode":"}\n\nexport function signalValidatedProcessGroup(\n  pgid,\n  environmentFragment,\n  signal,\n  groupState = { stopped: false, anchorPid: null },\n  operations = processGroupSignalOperations\n) {\n  if (!Number.isInteger(pgid) || pgid <= 0) {\n    return false\n  }\n  let members\n  try {\n    members = operations.processIdentities(true).filter((identity) => identity.pgid === pgid)\n  } catch (error) {\n    const recoveryErrors = compensateStoppedGroup(pgid, groupState, operations)\n    if (recoveryErrors.length > 0) {\n      throw new AggregateError(\n        [error, ...recoveryErrors],\n        'Benchmark process group recovery failed before validation'\n      )\n    }\n    throw error\n  }\n  if (members.length === 0) {\n    const recoveryErrors = compensateStoppedGroup(pgid, groupState, operations)\n    if (recoveryErrors.length > 0) {\n      throw new AggregateError(recoveryErrors, 'Benchmark missing process group recovery failed')\n    }\n    return false\n  }\n  if (members.some((identity) => !identity.command.includes(environmentFragment))) {\n    const ownershipError = new Error('Benchmark process group no longer belongs to this trial')\n    const recoveryErrors = compensateStoppedGroup(pgid, groupState, operations)\n    if (recoveryErrors.length > 0) {\n      throw new AggregateError(","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/macos-computer-helper-owner-loss-processes.mjs#L220-L256","documentation":"In signalValidatedProcessGroup, the initial call to processIdentities(true) (which runs `ps eww -axo pid=,pgid=,command=`) throws an error before the group can even be validated. The recovery function compensateStoppedGroup (sending SIGCONT to stopped/anchor PIDs) also produces errors. Both the ps failure and recovery failures are wrapped in an AggregateError.","triggerScenarios":"processIdentities(true) throws (ps eww fails: output exceeds 20MB maxBuffer, EACCES, or ps binary not found) at line 234. Then compensateStoppedGroup also encounters non-ESRCH errors when trying to SIGCONT the stopped group or anchor PID. recoveryErrors.length > 0 at line 237.","commonSituations":"System with an extremely large number of processes causing ps eww output to exceed the 20MB buffer; permission restrictions on ps; the stopped/anchor PID was recycled to a process owned by another user (EPERM on SIGCONT); ps not in PATH.","solutions":["Check why `ps eww -axo pid=,pgid=,command=` failed — increase maxBuffer or reduce process count","Inspect AggregateError.errors: errors[0] is the ps failure, errors[1+] are recovery failures","Ensure the process group's stopped/anchor PIDs are still owned by the benchmark user","If ps output is too large, consider filtering to the target pgid earlier in the pipeline"],"exampleFix":"// before: ps eww may exceed buffer on systems with many processes\nconst output = execFileSync('ps', ['eww', '-axo', 'pid=,pgid=,command='], {\n  encoding: 'utf8',\n  maxBuffer: 20 * 1024 * 1024\n})\n\n// after: increase buffer or scope the query\nconst output = execFileSync('ps', ['eww', '-axo', 'pid=,pgid=,command='], {\n  encoding: 'utf8',\n  maxBuffer: 100 * 1024 * 1024\n})","handlingStrategy":"try-catch","validationCode":"// Pre-check: ensure ps eww will not overflow\nconst psCount = execFileSync('ps', ['-axo', 'pid='], { encoding: 'utf8' }).trim().split('\\n').length\nif (psCount > 100_000) {\n  throw new Error(`Process count (${psCount}) too high for ps eww — reduce before running`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  signalValidatedProcessGroup(pgid, envFragment, signal, groupState)\n} catch (error) {\n  if (error instanceof AggregateError) {\n    // errors[0] = ps failure, errors[1+] = recovery failures\n    const [psError, ...recoveryErrors] = error.errors\n    console.error('ps eww failed:', psError.message)\n    recoveryErrors.forEach(e => console.error('Recovery failed:', e.message))\n  }\n  throw error\n}","preventionTips":["Increase the ps maxBuffer if the system has many processes","Ensure the benchmark user has permissions to inspect all processes in the group","Reset groupState (stopped, anchorPid) between independent operations to avoid stale recovery targets"],"tags":["process-group","recovery","aggregate-error","ps"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}