openai/codex · critical

failed to open bundled bubblewrap {}: {err}

Error message

failed to open bundled bubblewrap {}: {err}

What it means

The Linux sandbox can exec a bundled copy of bubblewrap instead of a system one. BundledBwrapLauncher::exec() opens the previously resolved bwrap path (from the install context's codex-resources directory or legacy locations next to the binary) and panics if File::open fails: the launcher found an executable file during discovery, but it cannot be opened when the sandbox is about to start.

Source

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

const SHA256_HEX_LEN: usize = 64;
const NULL_SHA256_DIGEST: [u8; 32] = [0; 32];

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct BundledBwrapLauncher {
    program: AbsolutePathBuf,
}

pub(crate) fn launcher() -> Option<BundledBwrapLauncher> {
    let current_exe = std::env::current_exe().ok()?;
    find_for_install_context(InstallContext::current())
        .or_else(|| find_legacy_for_exe(&current_exe))
        .map(|program| BundledBwrapLauncher { program })
}

impl BundledBwrapLauncher {
    pub(crate) fn exec(&self, argv: Vec<String>, preserved_files: Vec<File>) -> ! {
        let bwrap_file = File::open(self.program.as_path()).unwrap_or_else(|err| {
            panic!(
                "failed to open bundled bubblewrap {}: {err}",
                self.program.as_path().display()
            )
        });
        if let Err(err) = verify_digest(&bwrap_file, expected_sha256(), self.program.as_path()) {
            eprintln!("{err}");
            std::process::exit(crate::BUNDLED_BWRAP_DIGEST_VERIFICATION_FAILURE_EXIT_CODE);
        }

        make_files_inheritable(&preserved_files);

        let fd_path = format!("/proc/self/fd/{}", bwrap_file.as_raw_fd());
        let program_cstring = CString::new(fd_path.as_str())
            .unwrap_or_else(|err| panic!("invalid bundled bubblewrap fd path: {err}"));
        let cstrings = argv_to_cstrings(&argv);
        let mut argv_ptrs: Vec<*const c_char> = cstrings
            .iter()
            .map(CString::as_c_str)

View on GitHub (pinned to 339751715c)

Solutions

  1. Inspect the path printed in the panic: ls -l it and confirm the file still exists and is readable and executable by the running user.
  2. Reinstall the codex package so the bundled resources are re-extracted intact.
  3. Check security software and audit logs (SELinux denials, EDR quarantine) and restore or exclude the binary.
  4. If the environment cannot host the bundled binary, install system bubblewrap so the sandbox uses the system path instead.
Defensive patterns

Strategy: validation

Validate before calling

use std::os::unix::fs::PermissionsExt;
fn bundled_bwrap_usable(path: &std::path::Path) -> bool {
    let Ok(meta) = std::fs::metadata(path) else { return false; };
    meta.is_file()
        && meta.permissions().mode() & 0o111 != 0
        && std::fs::File::open(path).is_ok()
}
if !bundled_bwrap_usable(&path) {
    // repair the installation or fall back to system bwrap before launching
}

Try / catch

The panic happens inside exec() immediately before execv; catch_unwind does not help because the surrounding flow expects exec to replace the process. Validate the path beforehand and repair or fall back instead of catching.

Prevention

When it happens

Trigger: Between launcher() discovery and exec(), the bwrap file was deleted, renamed, or had permissions/ownership changed; the installation directory sits on a mount that went away (unmounted FUSE/archive); EIO/ENXIO from a failing disk; EACCES after the file mode or a parent directory's search permission changed.

Common situations: Broken or partially extracted npm/package installs where codex-resources/bwrap exists but is unreadable; antivirus/EDR quarantining the binary mid-session; resources on removable or network mounts; system cleaners removing unknown executables.

Related errors


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