openai/codex · error

MCP HTTP headers helper failed to start

Error message

MCP HTTP headers helper failed to start: {error}

What it means

Windows path of run_helper(): the Job Object was created, but spawn_contained() could not start %COMSPEC% /Q /D /C "<command" — the child never launched. The helper runs with a cleared environment (env_clear()) plus only the minimal MCP-server env, so PATH resolution, the configured cwd, and COMSPEC itself are the usual suspects. This is a spawn failure, distinct from the helper running and exiting non-zero.

Solutions

  1. Use an absolute path to the helper executable in the command string
  2. Verify the configured cwd exists and is readable
  3. Test locally: cmd /Q /D /C "<command>" from that cwd with a stripped environment (env -i equivalent)
  4. Check COMSPEC is set to an accessible shell on the host

Example fix

# before
httpHeadersHelper = "my-auth-helper --json"

# after
httpHeadersHelper = "C:\\Tools\\my-auth-helper.exe --json"
Defensive patterns

Strategy: validation

Validate before calling

:: Test on Windows from the configured cwd with a minimal environment before wiring in the helper
cd /d "%MCP_CWD%" && cmd /Q /D /C "%HTTP_HEADERS_HELPER%" >NUL
if errorlevel 1 (echo helper failed to start/exit nonzero)

Type guard

fn is_helper_spawn_failure(error: &anyhow::Error) -> bool {
    error.to_string().contains("headers helper failed to start")
}

Prevention

When it happens

Trigger: An httpHeadersHelper command that cmd.exe cannot execute: bare executable name not resolvable on the minimal PATH, missing configured cwd directory, malformed quoting, or a COMSPEC pointing at an unavailable shell.

Common situations: Helpers referencing tools by bare name (my-helper.exe) that happen to be on the interactive PATH but not the cleared env's; cwd configured to a deleted/renamed folder; locked-down machines where cmd.exe is blocked by policy.

Related errors


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

Appendix: source

Thrown at codex-rs/rmcp-client/src/http_headers.rs:304

    #[cfg(unix)]
    process.process_group(0);
    process
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .stderr(Stdio::null())
        .current_dir(cwd)
        // Match local MCP subprocess policy; arbitrary ambient variables are not inherited.
        .env_clear()
        .envs(create_env_for_mcp_server(/*extra_env*/ None, &[])?)
        .kill_on_drop(true);

    #[cfg(windows)]
    let (child, job) = {
        let job = codex_utils_pty::JobObject::create_without_breakaway()
            .map_err(|error| anyhow!("MCP HTTP headers helper containment failed: {error}"))?;
        let child = job
            .spawn_contained(&mut process)
            .map_err(|error| anyhow!("MCP HTTP headers helper failed to start: {error}"))?;
        (child, job)
    };
    #[cfg(not(windows))]
    let child = process
        .spawn()
        .map_err(|error| anyhow!("MCP HTTP headers helper failed to start: {error}"))?;
    let mut process = HelperProcess {
        #[cfg(unix)]
        process_group_id: child
            .id()
            .ok_or_else(|| anyhow!("MCP HTTP headers helper process id was unavailable"))?,
        child,
        #[cfg(windows)]
        job,
    };
    let output = tokio::time::timeout(HELPER_TIMEOUT, async {
        let stdout = process
            .child

View on GitHub (pinned to 339751715c)