astrid-runtime/astrid · error · io::Error
opened representation entry is redirected or not a regular f
Error message
opened representation entry is redirected or not a regular file
What it means
validate_opened_regular stats an already-opened representation File and rejects it if it is not a regular file or if opened_file_is_redirected reports redirection (e.g. opened via /proc-style magic link). This InvalidData error ensures the handle the library holds truly refers to a regular file at open time.
Source
Thrown at crates/astrid-storage/src/engine/durable/representations/contiguous/namespace.rs:121
#[cfg(unix)]
{
use cap_std::fs::OpenOptionsExt as _;
options.custom_flags(libc::O_NOFOLLOW | libc::O_NONBLOCK);
}
#[cfg(windows)]
{
use cap_std::fs::OpenOptionsExt as _;
use windows_sys::Win32::Storage::FileSystem::FILE_FLAG_OPEN_REPARSE_POINT;
options.custom_flags(FILE_FLAG_OPEN_REPARSE_POINT);
}
}
pub(in crate::engine::durable::representations) fn validate_opened_regular(
file: &File,
) -> io::Result<()> {
let metadata = file.metadata()?;
if !metadata.is_file() || opened_file_is_redirected(&metadata) {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"opened representation entry is redirected or not a regular file",
));
}
Ok(())
}
#[cfg(windows)]
fn opened_file_is_redirected(metadata: &std::fs::Metadata) -> bool {
use std::os::windows::fs::MetadataExt as _;
use windows_sys::Win32::Storage::FileSystem::FILE_ATTRIBUTE_REPARSE_POINT;
metadata.file_attributes() & FILE_ATTRIBUTE_REPARSE_POINT != 0
}
#[cfg(not(windows))]
const fn opened_file_is_redirected(_metadata: &std::fs::Metadata) -> bool {
falseView on GitHub (pinned to affd8760f4)
Solutions
- Reopen the file after the racing writer has finished; the validation passes on a stable file
- Eliminate concurrent processes that replace representation files during reads/writes
- Use the library's locking or a single-owner process model for the store
- Audit for symlink/magic-link exposure of the store path and block it at the filesystem level
Example fix
// before
fs::write("store/rep/f", data) // another job replaces f with a fifo mid-open
// after
exclusive_lock(store); write; unlock Defensive patterns
Strategy: retry
Validate before calling
// verify path target before opening
let md = path.symlink_metadata()?;
if !md.is_file() { return Err("representation entry is not a regular file"); } Try / catch
match open_file_result {
Err(e) if e.kind() == io::ErrorKind::InvalidData => {
// likely a swap race; wait for writer completion and reopen
std::thread::sleep(Duration::from_millis(50));
open_file(path)
}
r => r,
} Prevention
- Avoid concurrent replacement of representation files while readers are open
- Use the store single-owner / lock discipline
- Keep the store off paths other users can modify
- Treat repeated failures as a tampering or corruption signal
When it happens
Trigger: Calling open_file on an entry that was swapped to a non-regular object between path validation and open, or opened through a redirection (e.g. O_PATH/magic-link tricks) so metadata on the handle reports a non-file.
Common situations: TOCTOU races with concurrent deletion/recreation of representation files; exploits using magic symlinks to redirect opens; corrupted namespace entries pointing at devices or FIFOs.
Related errors
- legacy state source changed type: {}
- legacy source changed while opening: {}
- principal-store directory changed while it was opened
- read materialized capsule metadata: {error:#}
- read materialized capsule authority: {error:#}
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/f1d61e9e94b7a2bf.
Report an issue: GitHub.