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

ECC runner did not expose a process id

Error message

ECC runner did not expose a process id

What it means

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.

Source

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

        .arg(session_id)
        .arg("--task")
        .arg(task)
        .arg("--agent")
        .arg(agent_type)
        .arg("--cwd")
        .arg(working_dir)
        .stdin(Stdio::null())
        .stdout(Stdio::null())
        .stderr(Stdio::from(stderr_log));
    configure_background_runner_command(&mut command);

    let child = command
        .spawn()
        .with_context(|| format!("Failed to spawn ECC runner from {}", current_exe.display()))?;

    child
        .id()
        .ok_or_else(|| anyhow::anyhow!("ECC runner did not expose a process id"))?;
    Ok(())
}

fn background_runner_stderr_log_path(working_dir: &Path, session_id: &str) -> PathBuf {
    working_dir
        .join(".claude")
        .join("ecc2")
        .join("logs")
        .join(format!("{session_id}.runner-stderr.log"))
}

#[cfg(windows)]
fn detached_creation_flags() -> u32 {
    const DETACHED_PROCESS: u32 = 0x0000_0008;
    const CREATE_NEW_PROCESS_GROUP: u32 = 0x0000_0200;
    DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP
}

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Verify the ECC runner executable exists and is runnable at the path returned by current_exe()
  2. Check stderr logs at the runner-stderr log path for immediate-exit errors
  3. Retry the spawn after confirming the executable is valid
  4. On platforms where PID is unreliable, consider using process groups or named locks instead
Defensive patterns

Strategy: try-catch

Try / catch

match spawn_ecc_runner(working_dir, session_id) {
    Ok(()) => {},
    Err(e) if e.to_string().contains("did not expose a process id") => {
        tracing::error!("ECC runner exited immediately; check stderr log at {}",
            background_runner_stderr_log_path(working_dir, session_id).display());
        return Err(e);
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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