openai/codex · error

failed to read synthetic bubblewrap mount marker in {}: {err

Error message

failed to read synthetic bubblewrap mount marker in {}: {err}

What it means

While iterating read_dir results in synthetic_mount_marker_dir_has_active_process_matching, every DirEntry resolution error panics. On Linux, entries disappearing mid-iteration does not produce an error, so this indicates real getdents-time trouble: kernel I/O or ENOMEM under pressure, or an external process mutating the directory while ignoring the flock that serializes registry access.

Source

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

fn synthetic_mount_marker_dir_has_active_process(marker_dir: &Path) -> bool {
    synthetic_mount_marker_dir_has_active_process_matching(marker_dir, |_| true)
}

fn synthetic_mount_marker_dir_has_active_process_matching(
    marker_dir: &Path,
    matches_marker: impl Fn(&Path) -> bool,
) -> bool {
    let entries = match fs::read_dir(marker_dir) {
        Ok(entries) => entries,
        Err(err) if err.kind() == std::io::ErrorKind::NotFound => return false,
        Err(err) => panic!(
            "failed to read synthetic bubblewrap mount marker directory {}: {err}",
            marker_dir.display()
        ),
    };
    for entry in entries {
        let entry = entry.unwrap_or_else(|err| {
            panic!(
                "failed to read synthetic bubblewrap mount marker in {}: {err}",
                marker_dir.display()
            )
        });
        let path = entry.path();
        let Some(pid) = path
            .file_name()
            .and_then(|name| name.to_str())
            .and_then(|name| name.parse::<libc::pid_t>().ok())
        else {
            continue;
        };
        if !process_is_active(pid) {
            match fs::remove_file(&path) {
                Ok(()) => {}
                Err(err) if err.kind() == std::io::ErrorKind::NotFound => {}
                Err(err) => panic!(
                    "failed to remove stale synthetic bubblewrap mount marker {}: {err}",

View on GitHub (pinned to 339751715c)

Solutions

  1. Stop external scripts and tools from mutating the registry while sessions run.
  2. Check dmesg for I/O errors and OOM events.
  3. With all codex processes stopped, clear the registry root and retry.
  4. If it recurs with no external writers, capture strace -e getdents64 output and report upstream.

Example fix

# before: cron races the launcher inside the registry
*/5 * * * * find /tmp/codex-bwrap-synthetic-mount-targets-* -delete

# after: never mutate the registry externally; remove it only when nothing runs
# rm -rf /tmp/codex-bwrap-synthetic-mount-targets-$(id -u)  # sessions stopped
Defensive patterns

Strategy: retry

Validate before calling

fn registry_enumerates_cleanly() -> bool {
    let root = std::env::temp_dir().join(format!(
        "codex-bwrap-synthetic-mount-targets-{}",
        unsafe { libc::geteuid() }
    ));
    std::fs::read_dir(&root)
        .map(|entries| entries.all(|e| e.is_ok()))
        .unwrap_or(true)
}

Prevention

When it happens

Trigger: Registering or cleaning up synthetic or protected targets while an external writer (cleanup script, monitoring tool) mutates the marker dir without the registry lock, or while the storage layer reports enumeration errors.

Common situations: Homegrown cron jobs cleaning /tmp racing active sessions; monitoring agents touching the dir; failing tmpfs or disk; memory pressure surfacing as ENOMEM.

Related errors


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