{"record":{"id":"995fc3631260694d","repo":"affaan-m/ECC","slug":"claude-code-did-not-expose-a-process-id","errorCode":null,"errorMessage":"Claude Code did not expose a process id","messagePattern":"Claude Code did not expose a process id","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"ecc2/src/session/manager.rs","lineNumber":3570,"sourceCode":"        task,\n        session_id,\n        working_dir,\n        None,\n    );\n    let child = command\n        .stdout(Stdio::null())\n        .stderr(Stdio::null())\n        .spawn()\n        .with_context(|| {\n            format!(\n                \"Failed to spawn Claude Code from {}\",\n                agent_program.display()\n            )\n        })?;\n\n    child\n        .id()\n        .ok_or_else(|| anyhow::anyhow!(\"Claude Code did not expose a process id\"))\n}\n\nasync fn stop_session_with_options(\n    db: &StateStore,\n    id: &str,\n    cleanup_worktree: bool,\n) -> Result<()> {\n    let session = resolve_session(db, id)?;\n    stop_session_recorded(db, &session, cleanup_worktree)\n}\n\nfn stop_session_recorded(db: &StateStore, session: &Session, cleanup_worktree: bool) -> Result<()> {\n    if let Some(pid) = session.pid {\n        kill_process(pid)?;\n    }\n\n    db.update_pid(&session.id, None)?;\n    db.update_state(&session.id, &SessionState::Stopped)?;","sourceCodeStart":3552,"sourceCodeEnd":3588,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/ecc2/src/session/manager.rs#L3552-L3588","documentation":"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.","triggerScenarios":"The spawned Claude Code process exits before child.id() is called, or the platform does not expose a PID for the spawned child.","commonSituations":"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.","solutions":["Verify claude (or the configured agent_program) is installed and on PATH","Check that agent_program resolves to a valid executable path via agent_program()","Inspect stderr output for immediate-exit clues before the null redirect takes effect","Ensure the spawn environment has the correct PATH and working directory"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match spawn_claude_code(agent_program, working_dir) {\n    Ok(pid) => Ok(pid),\n    Err(e) if e.to_string().contains(\"did not expose a process id\") => {\n        tracing::error!(\"Claude Code at {} exited immediately; verify it is installed and on PATH\",\n            agent_program.display());\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Verify the claude binary (or configured agent_program) is installed and on PATH before spawning","Run the agent binary manually to confirm it starts without errors","Check that agent_program() resolves to a valid executable in health checks"],"tags":["process","claude-code","spawn","pid"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}