thedotmack/claude-mem · warning

Failed to reap orphaned chroma-mcp descendant

Error message

Failed to reap orphaned chroma-mcp descendant

What it means

During cleanup the manager walks orphaned chroma-mcp descendant processes and SIGKILLs them. If process.kill fails with an errno other than ESRCH (process already gone), this warning is logged; the orphan may still be running.

Solutions

  1. Check the logged errno: EPERM means run the cleanup under the same user/with sufficient privileges.
  2. Verify the pid still belongs to a chroma-mcp descendant and kill it manually (kill -9 <pid>).
  3. In containers, ensure the reaper shares the PID namespace and has CAP_KILL if needed.
  4. If benign and recurring, confirm the process exits on its own and the warning is ignorable.

Example fix

// before
if (code !== 'ESRCH') { logger.warn(...); }
// after: handle EPERM explicitly with guidance
if (code === 'EPERM') {
  logger.warn('CHROMA_MCP', `Cannot kill orphan ${pid}: permission denied; kill manually`);
} else if (code !== 'ESRCH') {
  logger.warn('CHROMA_MCP', 'Failed to reap orphaned chroma-mcp descendant', { pid, code });
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check you can signal the pid first
try {
  process.kill(pid, 0); // existence/permission probe
} catch (e) {
  console.log(`pid ${pid} not signallable: ${e.code}`);
}

Try / catch

try { process.kill(pid, 'SIGKILL'); }
catch (e) {
  const code = (e as NodeJS.ErrnoException).code;
  if (code !== 'ESRCH') console.warn(`reap failed pid=${pid} code=${code}`);
}

Prevention

When it happens

Trigger: SIGKILL on a descendant pid raises EPERM (owned by another user), EINVAL, or another errno. Only ESRCH (no such process) is silently tolerated.

Common situations: Reaper running as a different user than the process that spawned chroma-mcp, containerized setups restricting signals between processes, or pid reuse races.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/4840fa7f49f8db73. Report an issue: GitHub.

Appendix: source

Thrown at src/services/sync/ChromaMcpManager.ts:1178

    const seen = new Set<number>();

    for (const { pid, startToken } of entries) {
      if (seen.has(pid)) continue;
      seen.add(pid);
      if (!isPidAlive(pid)) continue;

      if (!isSameProcess(pid, startToken)) {
        logger.debug('CHROMA_MCP', 'Skipping reap: PID was recycled since the snapshot', { pid });
        continue;
      }

      try {
        process.kill(pid, 'SIGKILL');
        logger.debug('CHROMA_MCP', 'Reaped orphaned chroma-mcp descendant', { pid });
      } catch (error) {
        const code = (error as NodeJS.ErrnoException).code;
        if (code !== 'ESRCH') {
          logger.warn('CHROMA_MCP', 'Failed to reap orphaned chroma-mcp descendant', {
            pid,
            code,
          });
        }
      }
    }
  }

  private async disposeActivePrewarm(): Promise<void> {
    const prewarmChild = this.activePrewarmChild;
    const tracked = this.activePrewarmTracked;
    if (!prewarmChild) {
      return;
    }
    if (this.activePrewarmChild === prewarmChild) {
      this.activePrewarmChild = null;
      this.activePrewarmTracked = null;
    }

View on GitHub (pinned to d8bc9755e7)