openai/codex · error · std::io::Error

InvalidInput

InvalidInput

Error message

Refusing to create helper binaries under temporary dir {temp_root:?} (codex_home: {codex_home:?})

What it means

At startup the codex binary creates arg0-dispatch helper symlinks (apply_patch and friends) under CODEX_HOME. In release builds (cfg(not(debug_assertions))) prepare_path_entry_for_codex_aliases refuses to place those helpers when the resolved codex home lies under std::env::temp_dir(), returning io::ErrorKind::InvalidInput with this message. Helpers in a volatile temp directory would vanish under tmp cleaners and break PATH-based dispatch; the guard is compiled out in debug builds to ease local testing.

Source

Thrown at codex-rs/arg0/src/lib.rs:347

///   with the hidden `--codex-run-as-apply-patch` flag.
///
/// Returns the temporary directory guard and the PATH value that prepends the
/// temporary directory so `apply_patch` can be on the PATH without requiring the
/// user to install a separate executable, simplifying the deployment of Codex
/// CLI.
/// Note: In debug builds the temp-dir guard is disabled to ease local testing.
///
/// IMPORTANT: Callers must update PATH before multiple threads are spawned.
fn prepare_path_entry_for_codex_aliases(
    existing_path: Option<OsString>,
) -> std::io::Result<(Arg0PathEntryGuard, OsString)> {
    let codex_home = find_codex_home()?;
    #[cfg(not(debug_assertions))]
    {
        // Guard against placing helpers in system temp directories outside debug builds.
        let temp_root = std::env::temp_dir();
        if codex_home.starts_with(&temp_root) {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                format!(
                    "Refusing to create helper binaries under temporary dir {temp_root:?} (codex_home: {codex_home:?})"
                ),
            ));
        }
    }

    std::fs::create_dir_all(&codex_home)?;
    // Use a CODEX_HOME-scoped temp root to avoid cluttering the top-level directory.
    let temp_root = codex_home.join("tmp").join("arg0");
    std::fs::create_dir_all(&temp_root)?;
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;

        // Ensure only the current user can access the temp directory.
        std::fs::set_permissions(&temp_root, std::fs::Permissions::from_mode(0o700))?;

View on GitHub (pinned to 339751715c)

Solutions

  1. Point CODEX_HOME at a persistent directory outside the temp root (e.g. $HOME/.codex) and re-run
  2. Unset CODEX_HOME to fall back to the default home directory
  3. If TMPDIR was overridden to cover the home directory, fix TMPDIR instead
  4. Local development only: run a debug build, where the guard is disabled

Example fix

# before
export CODEX_HOME="$(mktemp -d)" # release build refuses: home is under temp dir

# after
export CODEX_HOME="$HOME/.codex" # persistent location outside temp_dir()
Defensive patterns

Strategy: validation

Validate before calling

let codex_home = std::env::var_os("CODEX_HOME")
    .map(PathBuf::from)
    .unwrap_or_else(|| default_codex_home());
if codex_home.starts_with(std::env::temp_dir()) {
    // pick a persistent home before launching the release binary
}

Try / catch

// when spawning codex: match on io::ErrorKind::InvalidInput from startup,
// re-point CODEX_HOME to a persistent directory, and retry the launch once.

Prevention

When it happens

Trigger: Running a release codex binary with CODEX_HOME set to a path under TMPDIR (for example CODEX_HOME=/tmp/codex-home), or TMPDIR redefined to a parent of the resolved home. Common in sandboxes, containers, CI, and test harnesses that isolate state under /tmp.

Common situations: CI containers exporting CODEX_HOME=$(mktemp -d); sandboxed dev shells with unusual TMPDIR; wrapper scripts pointing CODEX_HOME at a scratch directory.

Related errors


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