xai-org/grok-build · error · io::Error

journal is not a regular file: {}

Error message

journal is not a regular file: {}

What it means

read_journal_bounded hardens journal loading: it uses symlink_metadata to inspect the entry without following links and rejects anything that is a symlink or not a regular file, with io::ErrorKind::InvalidData. This prevents a journal path from silently redirecting reads to another file or device.

Source

Thrown at crates/codegen/xai-workflow/src/journal.rs:258

        let Some(new_len) = self.last_line_start else {
            return Err(JournalError::Io(std::io::Error::other(
                "journal cannot locate the trailing entry's byte offset",
            )));
        };
        if let Some(path) = &self.path {
            truncate_tail(path, new_len)?;
        }
        self.entries.pop();
        self.bytes = new_len;
        self.last_line_start = None;
        Ok(true)
    }
}

fn read_journal_bounded(path: &Path) -> std::io::Result<Vec<u8>> {
    let metadata = std::fs::symlink_metadata(path)?;
    if metadata.file_type().is_symlink() || !metadata.is_file() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidData,
            format!("journal is not a regular file: {}", path.display()),
        ));
    }
    if metadata.len() > MAX_JOURNAL_BYTES {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidData,
            format!("journal exceeds {MAX_JOURNAL_BYTES} bytes"),
        ));
    }
    let mut options = std::fs::OpenOptions::new();
    options.read(true);
    #[cfg(unix)]
    {
        use std::os::unix::fs::OpenOptionsExt;
        options.custom_flags(libc::O_NOFOLLOW);
    }
    let file = options.open(path)?;

View on GitHub (pinned to bc7f02eddd)

Solutions

  1. Replace the symlink with a real regular file (move the target back into place: cp --remove-destination)
  2. Remove any directory/FIFO occupying the journal path so the library can create a fresh regular file
  3. Point the journal path configuration at a location you control as a plain file

Example fix

# before: journal is a symlink
$ ls -l journal  # journal -> /mnt/cloud/journal
# after
$ rm journal && cp /mnt/cloud/journal journal
Defensive patterns

Strategy: validation

Validate before calling

fn journal_is_regular(path: &Path) -> std::io::Result<bool> {
    let md = std::fs::symlink_metadata(path)?;
    Ok(!md.file_type().is_symlink() && md.is_file())
}
if journal_is_regular(&journal_path).unwrap_or(true) {
    load(&journal_path)?;
}

Type guard

fn journal_is_regular(path: &Path) -> std::io::Result<bool> {
    let md = std::fs::symlink_metadata(path)?;
    Ok(!md.file_type().is_symlink() && md.is_file())
}

Try / catch

if let Err(e) = load(&journal_path) {
    if e.kind() == std::io::ErrorKind::InvalidData {
        eprintln!("journal path is not a regular file: {e}; move/recreate it");
    }
    return Err(e.into());
}

Prevention

When it happens

Trigger: The journal path points to a symlink, directory, FIFO, socket, or device node instead of a regular file — e.g. a user symlinked the journal to another location, or a directory was created where the journal file should be.

Common situations: Users symlinking ~/.workflow/journal to a synced/cloud folder; provisioning scripts pre-creating a journal directory; mount points or special files left in the journal location.

Related errors


AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31). Data as JSON: /api/errors/69004f1ec990578b. Report an issue: GitHub.