openai/codex · error

invalid legacy bubblewrap fd mount: {error}

Error message

invalid legacy bubblewrap fd mount: {error}

What it means

When the system bubblewrap's --help does not advertise --ro-bind-fd, exec_bwrap falls back to translate_legacy_bwrap_fd_mounts, which rewrites --ro-bind-fd FD DEST into --ro-bind /proc/self/fd/FD DEST plus --verify-fd-mount FD:DEST arguments for the trusted inner stage. Any argv that cannot be translated (missing '--' separator, missing or non-numeric fd, standard or duplicate fd, relative destination, missing inner command, or an inner command lacking --apply-seccomp-then-exec) makes the translation return Err, and exec_bwrap panics with this message before exec.

Source

Thrown at codex-rs/linux-sandbox/src/launcher.rs:45

    supports_argv0: bool,
    supports_ro_bind_fd: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct SystemBwrapCapabilities {
    supports_argv0: bool,
    supports_perms: bool,
    supports_ro_bind_fd: bool,
}

pub(crate) fn exec_bwrap(mut argv: Vec<String>, preserved_files: Vec<File>) -> ! {
    argv.insert(1, "--as-pid-1".to_string());

    match preferred_bwrap_launcher() {
        BubblewrapLauncher::System(launcher) => {
            if !launcher.supports_ro_bind_fd {
                translate_legacy_bwrap_fd_mounts(&mut argv)
                    .unwrap_or_else(|error| panic!("invalid legacy bubblewrap fd mount: {error}"));
            }
            exec_system_bwrap(&launcher.program, argv, preserved_files)
        }
        BubblewrapLauncher::Bundled(launcher) => launcher.exec(argv, preserved_files),
        BubblewrapLauncher::Unavailable => {
            panic!(
                "bubblewrap is unavailable: no system bwrap was found on PATH and no bundled \
                 codex-resources/bwrap binary was found next to the Codex executable"
            )
        }
    }
}

fn translate_legacy_bwrap_fd_mounts(argv: &mut Vec<String>) -> Result<(), String> {
    let command_separator = argv
        .iter()
        .position(|argument| argument == "--")
        .ok_or_else(|| "bubblewrap argv is missing the command separator '--'".to_string())?;

View on GitHub (pinned to 339751715c)

Solutions

  1. Upgrade bubblewrap to a build whose --help lists --ro-bind-fd, which skips the legacy translation entirely
  2. Restore the required shape: bwrap flags ... -- codex-linux-sandbox --apply-seccomp-then-exec -- command
  3. Let the launcher emit --ro-bind-fd flags instead of injecting them yourself
  4. Pin bwrap in CI and assert on its --help capabilities

Example fix

# before -- no '--' separator, translation fails and exec_bwrap panics
bwrap --as-pid-1 --ro-bind-fd 7 /tmp/socket-root /usr/bin/env -- true

# after -- separator and trusted inner stage present
bwrap --as-pid-1 --ro-bind-fd 7 /tmp/socket-root -- codex-linux-sandbox --apply-seccomp-then-exec -- true
Defensive patterns

Strategy: validation

Validate before calling

use std::process::Command;

fn bwrap_supports_ro_bind_fd(program: &std::path::Path) -> bool {
    match Command::new(program).arg("--help").output() {
        Ok(out) => {
            let text = format!(
                "{}{}",
                String::from_utf8_lossy(&out.stdout),
                String::from_utf8_lossy(&out.stderr)
            );
            text.contains("--ro-bind-fd")
        }
        Err(_) => false,
    }
}

if !bwrap_supports_ro_bind_fd(&bwrap_path) {
    validate_legacy_translatable_argv(&argv)?;
}

Try / catch

let pid = unsafe { libc::fork() };
if pid == 0 {
    exec_bwrap(argv, preserved_files); // diverges: execs or panics
}
let mut status = 0;
unsafe { libc::waitpid(pid, &mut status, 0) };
if !libc::WIFEXITED(status) || libc::WEXITSTATUS(status) != 0 {
    // child panicked before exec: surface bwrap capability and argv diagnostics
}

Prevention

When it happens

Trigger: An older distro bubblewrap without --ro-bind-fd combined with a malformed argv: dropping the '--' between bwrap flags and the inner command, or replacing the codex-linux-sandbox --apply-seccomp-then-exec stage with a plain command.

Common situations: Ubuntu 20.04/22.04-era bwrap packages; forks or scripts that assemble their own bwrap argv; refactors that reorder flags or remove the separator.

Related errors


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