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
- Replace the symlink with a real regular file (move the target back into place: cp --remove-destination)
- Remove any directory/FIFO occupying the journal path so the library can create a fresh regular file
- 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
- Don't symlink the journal path (e.g. into cloud-synced folders) — move the real file instead
- Ensure provisioning scripts don't create a directory or FIFO at the journal path
- Check the journal path with lstat before starting the workflow
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
- failed to read {}: {e}
- failed to open {}: {e}
- failed to replace {}: {e}
- path {:?} is outside the memory directory {:?}
- workflow artifact is not a regular file: {}
AI-assisted analysis of xai-org/grok-build@bc7f02eddd (2026-08-31).
Data as JSON: /api/errors/69004f1ec990578b.
Report an issue: GitHub.