openai/codex · error · anyhow::Error

pid-managed app-server shutdown is unsupported on this platf

Error message

pid-managed app-server shutdown is unsupported on this platform

What it means

PidBackend shuts the managed app-server down by sending SIGTERM through libc::kill on Unix. On non-Unix targets there is no signal implementation, so terminate_process is a #[cfg(not(unix))] stub that unconditionally bails with this message to keep the crate cross-compilable. The daemon's public entry points already reject non-Unix platforms up front (ensure_supported_platform in codex-rs/app-server-daemon/src/lib.rs:242), so hitting this means the pid backend was reached directly on a Windows build.

Source

Thrown at codex-rs/app-server-daemon/src/backend/pid.rs:563

#[cfg(unix)]
fn force_terminate_process_group(pid: u32) -> Result<()> {
    let raw_pid = libc::pid_t::try_from(pid)
        .with_context(|| format!("pid-managed updater pid {pid} is out of range"))?;
    let result = unsafe { libc::kill(-raw_pid, libc::SIGKILL) };
    if result == 0 {
        return Ok(());
    }
    let err = std::io::Error::last_os_error();
    if err.raw_os_error() == Some(libc::ESRCH) {
        return Ok(());
    }
    Err(err).with_context(|| format!("failed to force terminate pid-managed updater group {pid}"))
}

#[cfg(not(unix))]
fn terminate_process(_pid: u32) -> Result<()> {
    bail!("pid-managed app-server shutdown is unsupported on this platform")
}

#[cfg(not(unix))]
fn force_terminate_process(_pid: u32) -> Result<()> {
    bail!("pid-managed app-server shutdown is unsupported on this platform")
}

#[cfg(not(unix))]
fn force_terminate_process_group(_pid: u32) -> Result<()> {
    bail!("pid-managed updater shutdown is unsupported on this platform")
}

#[cfg(unix)]
async fn process_matches_record(record: &PidRecord) -> Result<bool> {
    if !process_exists(record.pid) {
        return Ok(false);
    }

View on GitHub (pinned to 339751715c)

Solutions

  1. Run the app-server daemon on macOS or Linux — the lifecycle is Unix-only by design and the platform gate in lib.rs is intentional.
  2. Call the public codex_app_server_daemon::run()/bootstrap() APIs instead of the pid backend directly, so the unsupported-platform check fires first with the clearer umbrella message.
  3. cfg-gate your own call sites with #[cfg(unix)] and emit a 'daemon stop requires a Unix host' error on other targets rather than letting the backend stub bail.
  4. Clear stale state (<CODEX_HOME>/state/*.pid and *.pid.lock left by another platform) before reusing the same CODEX_HOME.

Example fix

// before: compiles everywhere, bails at runtime on Windows
backend.stop().await?;

// after: gate the call site so non-Unix gets a clear, local error
#[cfg(unix)]
{
    backend.stop().await?;
}
#[cfg(not(unix))]
anyhow::bail!("app-server daemon stop requires a Unix host");
Defensive patterns

Strategy: validation

Validate before calling

// run before touching any daemon lifecycle API
if !cfg!(unix) {
    anyhow::bail!("codex app-server daemon lifecycle requires a Unix platform");
}

Try / catch

Not recoverable by catching: the bail is unconditional on non-Unix. If forced, branch on cfg!(unix) and degrade to a no-op with a warning instead of unwrap/expect on the Result.

Prevention

When it happens

Trigger: Compiling codex-app-server-daemon for Windows (or any non-Unix target) and driving a stop path that reaches PidBackend::terminate_process (codex-rs/app-server-daemon/src/backend/pid.rs:438), e.g. LifecycleCommand::Stop with a pid record present. On Unix the real SIGTERM implementation at pid.rs:517 is used instead and never produces this error.

Common situations: Running the daemon crate or its unit tests on a Windows dev machine; cross-compiling with cargo build --target *-windows-* and invoking lifecycle stop; reusing a CODEX_HOME whose state dir still holds a pid file written from WSL/Linux so a stop is attempted.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/ff1baf7beede4ec8. Report an issue: GitHub.