herdrdev/herdr · error · io::Error

failed to create unique scrollback temp file

Error message

failed to create unique scrollback temp file

What it means

open_focused_scrollback_in_editor needs a temp file for the pane's scrollback, so write_scrollback_temp_file retries with unique candidate names. If every attempt fails — either each name collided (AlreadyExists) or another I/O error occurred — it returns ErrorKind::AlreadyExists with 'failed to create unique scrollback temp file' (the fallback when even the collision loop produced no actionable error). In practice the temp directory is unwritable, full, or the name-generation space is exhausted.

Source

Thrown at src/app/input/navigate.rs:2016

        {
            use std::os::unix::fs::OpenOptionsExt;
            options.mode(0o600);
        }

        match options.open(&path) {
            Ok(mut file) => {
                file.write_all(content.as_bytes())?;
                return Ok(path);
            }
            Err(err) if err.kind() == io::ErrorKind::AlreadyExists => {
                last_collision = Some(err);
            }
            Err(err) => return Err(err),
        }
    }

    Err(last_collision.unwrap_or_else(|| {
        io::Error::new(
            io::ErrorKind::AlreadyExists,
            "failed to create unique scrollback temp file",
        )
    }))
}

fn unique_scrollback_path(attempt: u32) -> std::path::PathBuf {
    let nanos = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map(|duration| duration.as_nanos())
        .unwrap_or(0);
    std::env::temp_dir().join(format!(
        "herdr-scrollback-{}-{nanos}-{attempt}.txt",
        std::process::id()
    ))
}

#[cfg(test)]

View on GitHub (pinned to f457cff4f2)

Solutions

  1. Check TMPDIR (or /tmp) is writable and has free space: touch $TMPDIR/probe && df -h $TMPDIR.
  2. Set TMPDIR to a writable location with space before launching herdr.
  3. Clean up stale herdr scrollback temp files that may be causing collisions.
  4. If it persists, capture the underlying last_collision error in tracing to see the real OS error (permissions vs ENOSPC vs name collisions).

Example fix

# before
TMPDIR=/readonly/tmp herdr

# after
mkdir -p ~/.cache/herdr-tmp
TMPDIR=~/.cache/herdr-tmp herdr
Defensive patterns

Strategy: fallback

Validate before calling

let tmp = std::env::temp_dir();
let probe = tmp.join(".herdr_probe");
std::fs::write(&probe, b"")?; // fails fast with the real OS error if TMPDIR is unusable
std::fs::remove_file(&probe)?;

Try / catch

match write_scrollback_temp_file(&scrollback) {
    Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {
        // temp dir unusable or saturated: fall back to in-app viewer, surface actionable message to user
    }
    other => other,
}

Prevention

When it happens

Trigger: Calling open_focused_scrollback_in_editor when the temp dir (e.g. /tmp or TMPDIR) is not writable, full (ENOSPC), or has thousands of same-prefix files making unique-name retries collide; also when the temp dir does not exist.

Common situations: TMPDIR pointing to a read-only or missing directory in containers/sandboxes; disk-full CI runners; sandboxed apps denied temp writes; leftover herdr scrollback temp files accumulating from crashes.

Related errors


AI-assisted analysis of herdrdev/herdr@f457cff4f2 (2026-08-28). Data as JSON: /api/errors/f82d3250b1d49408. Report an issue: GitHub.