affaan-m/ECC · critical · anyhow::Error

Claude Code did not expose a process id

Error message

Claude Code did not expose a process id

What it means

After spawning the Claude Code agent process with Stdio::null for stdout/stderr, the code calls child.id() to get the PID for session lifecycle management. If child.id() returns None, the process cannot be tracked, stopped, or heartbeat-checked, so the function bails immediately.

Source

Thrown at ecc2/src/session/manager.rs:3570

        task,
        session_id,
        working_dir,
        None,
    );
    let child = command
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn()
        .with_context(|| {
            format!(
                "Failed to spawn Claude Code from {}",
                agent_program.display()
            )
        })?;

    child
        .id()
        .ok_or_else(|| anyhow::anyhow!("Claude Code did not expose a process id"))
}

async fn stop_session_with_options(
    db: &StateStore,
    id: &str,
    cleanup_worktree: bool,
) -> Result<()> {
    let session = resolve_session(db, id)?;
    stop_session_recorded(db, &session, cleanup_worktree)
}

fn stop_session_recorded(db: &StateStore, session: &Session, cleanup_worktree: bool) -> Result<()> {
    if let Some(pid) = session.pid {
        kill_process(pid)?;
    }

    db.update_pid(&session.id, None)?;
    db.update_state(&session.id, &SessionState::Stopped)?;

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Verify claude (or the configured agent_program) is installed and on PATH
  2. Check that agent_program resolves to a valid executable path via agent_program()
  3. Inspect stderr output for immediate-exit clues before the null redirect takes effect
  4. Ensure the spawn environment has the correct PATH and working directory
Defensive patterns

Strategy: try-catch

Try / catch

match spawn_claude_code(agent_program, working_dir) {
    Ok(pid) => Ok(pid),
    Err(e) if e.to_string().contains("did not expose a process id") => {
        tracing::error!("Claude Code at {} exited immediately; verify it is installed and on PATH",
            agent_program.display());
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: The spawned Claude Code process exits before child.id() is called, or the platform does not expose a PID for the spawned child.

Common situations: claude binary is not installed or not on PATH, causing spawn to succeed but the process to exit instantly. Platform-specific PID limitations. Race where the child exits between spawn and id() call.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/995fc3631260694d. Report an issue: GitHub.