openai/codex · critical

failed to normalize bundled bubblewrap path {}: {err}

Error message

failed to normalize bundled bubblewrap path {}: {err}

What it means

launcher() discovers a bundled bwrap in legacy locations relative to the current executable (exe_dir/codex-resources/bwrap, the package-target directory, an adjacent bwrap, bazel runfiles). find_legacy_for_exe converts the first executable candidate to AbsolutePathBuf and panics if the path is not absolute. Because candidates are joined onto the exe's parent directory, this only fires when std::env::current_exe() itself resolves to a relative path.

Source

Thrown at codex-rs/linux-sandbox/src/bundled_bwrap.rs:86

            "failed to exec bundled bubblewrap {} via {fd_path}: {err}",
            self.program.as_path().display()
        );
    }
}

fn find_for_install_context(context: &InstallContext) -> Option<AbsolutePathBuf> {
    context
        .bundled_resource("bwrap")
        .filter(|path| is_executable_file(path))
}

fn find_legacy_for_exe(exe: &Path) -> Option<AbsolutePathBuf> {
    legacy_candidates_for_exe(exe)
        .into_iter()
        .find(|candidate| is_executable_file(candidate))
        .map(|path| {
            AbsolutePathBuf::from_absolute_path(&path).unwrap_or_else(|err| {
                panic!(
                    "failed to normalize bundled bubblewrap path {}: {err}",
                    path.display()
                )
            })
        })
}

fn legacy_candidates_for_exe(exe: &Path) -> Vec<PathBuf> {
    let Some(exe_dir) = exe.parent() else {
        return Vec::new();
    };

    let mut candidates = Vec::new();
    candidates.push(exe_dir.join("codex-resources").join("bwrap"));
    if let Some(package_target_dir) = exe_dir.parent() {
        candidates.push(package_target_dir.join("codex-resources").join("bwrap"));
    }
    candidates.push(exe_dir.join("bwrap"));

View on GitHub (pinned to 339751715c)

Solutions

  1. Invoke the binary via an absolute path so exe-relative discovery yields absolute candidates.
  2. Mount /proc in the container or chroot so current_exe() resolves absolutely.
  3. Install via the supported package layout so InstallContext resolves codex-resources absolutely instead of falling back to legacy exe-relative discovery.

Example fix

# before
$ ./codex-linux/bin/codex ...   # relative invocation; current_exe() may stay relative without /proc

# after
$ /opt/codex/bin/codex ...      # absolute argv and /proc mounted
Defensive patterns

Strategy: validation

Validate before calling

// Before sandboxed commands, confirm exe resolution is absolute
match std::env::current_exe() {
    Ok(exe) if exe.is_absolute() => { /* legacy discovery is safe */ }
    Ok(_relative) => { /* re-exec self via an absolute path or refuse sandboxing */ }
    Err(_) => { /* /proc missing; mount it or disable the sandbox */ }
}

Prevention

When it happens

Trigger: Running the binary in an environment where current_exe() yields a relative path: exotic kernels, or chroots/containers where /proc/self/exe is unavailable or relative, so the join produces a relative candidate that AbsolutePathBuf::from_absolute_path rejects.

Common situations: Containers or chroots without /proc mounted; unusual FUSE/overlay filesystems; extremely rare on mainstream Linux and macOS where /proc/self/exe is absolute.

Related errors


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