openai/codex · error

failed to create synthetic bubblewrap mount marker directory

Error message

failed to create synthetic bubblewrap mount marker directory {}: {err}

What it means

register_synthetic_mount_targets (linux_run_main.rs:945) creates a marker directory per target under the per-uid registry ${TMPDIR}/codex-bwrap-synthetic-mount-targets-<euid>/<16-hex FNV-1a hash of the target path> (synthetic_mount_marker_dir, linux_run_main.rs:1332), holding one marker file per live PID so concurrent codex processes coordinate ownership and cleanup. create_dir_all panics when that root is not creatable or writable: TMPDIR unwritable or read-only, ENOSPC, or a non-directory component on the path.

Source

Thrown at codex-rs/linux-sandbox/src/linux_run_main.rs:954

        }
        let err = std::io::Error::last_os_error();
        if err.raw_os_error() == Some(libc::EINTR) {
            continue;
        }
        panic!("waitpid failed for bubblewrap child: {err}");
    }
}

fn register_synthetic_mount_targets(
    targets: &[crate::bwrap::SyntheticMountTarget],
) -> Vec<SyntheticMountTargetRegistration> {
    with_synthetic_mount_registry_lock(|| {
        targets
            .iter()
            .map(|target| {
                let marker_dir = synthetic_mount_marker_dir(target.path());
                fs::create_dir_all(&marker_dir).unwrap_or_else(|err| {
                    panic!(
                        "failed to create synthetic bubblewrap mount marker directory {}: {err}",
                        marker_dir.display()
                    )
                });
                let target = if target.preserves_pre_existing_path()
                    && synthetic_mount_marker_dir_has_active_synthetic_owner(&marker_dir)
                {
                    match target.kind() {
                        crate::bwrap::SyntheticMountTargetKind::EmptyFile => {
                            crate::bwrap::SyntheticMountTarget::missing(target.path())
                        }
                        crate::bwrap::SyntheticMountTargetKind::EmptyDirectory => {
                            crate::bwrap::SyntheticMountTarget::missing_empty_directory(
                                target.path(),
                            )
                        }
                    }
                } else {

View on GitHub (pinned to 339751715c)

Solutions

  1. Point TMPDIR at a writable directory with free space and rerun.
  2. Run ls -ld on the marker dir path printed in the panic to find the failing read-only or permission component.
  3. Free space or enlarge the tmpfs backing TMPDIR (mount -o remount,size=... /tmp).
  4. With no codex processes running, clear a stale registry: rm -rf ${TMPDIR:-/tmp}/codex-bwrap-synthetic-mount-targets-$(id -u).

Example fix

# before: TMPDIR resolves to a read-only location
TMPDIR=/mnt/ro-tmp codex exec --sandbox linux ...

# after: TMPDIR on a writable filesystem
TMPDIR=/var/tmp/codex codex exec --sandbox linux ...
Defensive patterns

Strategy: validation

Validate before calling

fn temp_registry_writable() -> std::io::Result<()> {
    let root = std::env::temp_dir().canonicalize()?;
    let probe = root.join(format!("codex-probe-{}", std::process::id()));
    std::fs::create_dir_all(&probe)?;
    std::fs::write(probe.join("p"), b"x")?;
    std::fs::remove_dir_all(&probe)?;
    Ok(())
}

Prevention

When it happens

Trigger: Any sandboxed run with synthetic mount targets (empty files or dirs the sandbox must materialize) where TMPDIR or /tmp is read-only, permission-denied for the effective uid, or full; TMPDIR inherited from a hardened service; a stale registry root with restrictive permissions.

Common situations: Hosts mounting /tmp read-only for hardening; TMPDIR pointed at a locked-down path; tmpfs size= limits reached; leftover registry roots with bad ownership after uid changes or restores.

Related errors


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