{"record":{"id":"69004f1ec990578b","repo":"xai-org/grok-build","slug":"journal-is-not-a-regular-file","errorCode":null,"errorMessage":"journal is not a regular file: {}","messagePattern":"journal is not a regular file: (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-workflow/src/journal.rs","lineNumber":258,"sourceCode":"        let Some(new_len) = self.last_line_start else {\n            return Err(JournalError::Io(std::io::Error::other(\n                \"journal cannot locate the trailing entry's byte offset\",\n            )));\n        };\n        if let Some(path) = &self.path {\n            truncate_tail(path, new_len)?;\n        }\n        self.entries.pop();\n        self.bytes = new_len;\n        self.last_line_start = None;\n        Ok(true)\n    }\n}\n\nfn read_journal_bounded(path: &Path) -> std::io::Result<Vec<u8>> {\n    let metadata = std::fs::symlink_metadata(path)?;\n    if metadata.file_type().is_symlink() || !metadata.is_file() {\n        return Err(std::io::Error::new(\n            std::io::ErrorKind::InvalidData,\n            format!(\"journal is not a regular file: {}\", path.display()),\n        ));\n    }\n    if metadata.len() > MAX_JOURNAL_BYTES {\n        return Err(std::io::Error::new(\n            std::io::ErrorKind::InvalidData,\n            format!(\"journal exceeds {MAX_JOURNAL_BYTES} bytes\"),\n        ));\n    }\n    let mut options = std::fs::OpenOptions::new();\n    options.read(true);\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::OpenOptionsExt;\n        options.custom_flags(libc::O_NOFOLLOW);\n    }\n    let file = options.open(path)?;","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-workflow/src/journal.rs#L240-L276","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: journal is a symlink\n$ ls -l journal  # journal -> /mnt/cloud/journal\n# after\n$ rm journal && cp /mnt/cloud/journal journal","handlingStrategy":"validation","validationCode":"fn journal_is_regular(path: &Path) -> std::io::Result<bool> {\n    let md = std::fs::symlink_metadata(path)?;\n    Ok(!md.file_type().is_symlink() && md.is_file())\n}\nif journal_is_regular(&journal_path).unwrap_or(true) {\n    load(&journal_path)?;\n}","typeGuard":"fn journal_is_regular(path: &Path) -> std::io::Result<bool> {\n    let md = std::fs::symlink_metadata(path)?;\n    Ok(!md.file_type().is_symlink() && md.is_file())\n}","tryCatchPattern":"if let Err(e) = load(&journal_path) {\n    if e.kind() == std::io::ErrorKind::InvalidData {\n        eprintln!(\"journal path is not a regular file: {e}; move/recreate it\");\n    }\n    return Err(e.into());\n}","preventionTips":["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"],"tags":["io","filesystem","security","symlink","rust"],"backgroundTag":"journal-not-regular-file","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}