{"record":{"id":"f0b8cdcdf6576eba","repo":"affaan-m/ECC","slug":"ecc-runner-did-not-expose-a-process-id","errorCode":null,"errorMessage":"ECC runner did not expose a process id","messagePattern":"ECC runner did not expose a process id","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"critical","filePath":"ecc2/src/session/manager.rs","lineNumber":3027,"sourceCode":"        .arg(session_id)\n        .arg(\"--task\")\n        .arg(task)\n        .arg(\"--agent\")\n        .arg(agent_type)\n        .arg(\"--cwd\")\n        .arg(working_dir)\n        .stdin(Stdio::null())\n        .stdout(Stdio::null())\n        .stderr(Stdio::from(stderr_log));\n    configure_background_runner_command(&mut command);\n\n    let child = command\n        .spawn()\n        .with_context(|| format!(\"Failed to spawn ECC runner from {}\", current_exe.display()))?;\n\n    child\n        .id()\n        .ok_or_else(|| anyhow::anyhow!(\"ECC runner did not expose a process id\"))?;\n    Ok(())\n}\n\nfn background_runner_stderr_log_path(working_dir: &Path, session_id: &str) -> PathBuf {\n    working_dir\n        .join(\".claude\")\n        .join(\"ecc2\")\n        .join(\"logs\")\n        .join(format!(\"{session_id}.runner-stderr.log\"))\n}\n\n#[cfg(windows)]\nfn detached_creation_flags() -> u32 {\n    const DETACHED_PROCESS: u32 = 0x0000_0008;\n    const CREATE_NEW_PROCESS_GROUP: u32 = 0x0000_0200;\n    DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP\n}\n","sourceCodeStart":3009,"sourceCodeEnd":3045,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/ecc2/src/session/manager.rs#L3009-L3045","documentation":"After spawning the ECC runner as a background child process, the code calls child.id() to retrieve the OS process ID for tracking. If the child has already exited or the platform does not expose a PID, child.id() returns None and the function bails. Without a PID, the session manager cannot stop or monitor the runner.","triggerScenarios":"The spawned ECC runner child process exits immediately before child.id() is called, or the platform/runtime does not assign a PID to the spawned process.","commonSituations":"Runner executable is missing or broken, causing immediate exit. Platform limitation where std::process::Child does not expose a PID. The child was already waited on by another code path.","solutions":["Verify the ECC runner executable exists and is runnable at the path returned by current_exe()","Check stderr logs at the runner-stderr log path for immediate-exit errors","Retry the spawn after confirming the executable is valid","On platforms where PID is unreliable, consider using process groups or named locks instead"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match spawn_ecc_runner(working_dir, session_id) {\n    Ok(()) => {},\n    Err(e) if e.to_string().contains(\"did not expose a process id\") => {\n        tracing::error!(\"ECC runner exited immediately; check stderr log at {}\",\n            background_runner_stderr_log_path(working_dir, session_id).display());\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Verify the ECC runner executable exists and runs before launching sessions","Monitor stderr logs for immediate-exit errors after spawn","Implement health checks that verify the runner PID is alive shortly after spawn"],"tags":["process","runner","spawn","pid"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}