astrid-runtime/astrid · error
legacy state source contains a special file
Error message
legacy state source contains a special file: {} What it means
Thrown when an entry inside the legacy state source tree is neither a directory nor a regular file — e.g. a FIFO, socket, or device node. Only plain files and directories are safe to validate and delete, so anything else aborts retirement with InvalidData before any data is removed.
Solutions
- Identify the entry (stat shows its type) and remove it — special files have no data relevant to retirement (rm on a fifo/socket removes only the node)
- Stop or relocate any process that creates sockets/pipes inside the state directory, so it stays regular-files-only
- Re-run retirement once the tree contains only regular files and directories
Example fix
# before: a fifo/socket inside the legacy tree /srv/astrid/var/state/surrealkv/control.sock (socket) # after: remove the node and re-run rm /srv/astrid/var/state/surrealkv/control.sock # restart the daemon with its socket path outside the state tree
Defensive patterns
Strategy: validation
Validate before calling
fn tree_has_special_files(root: &Path) -> std::io::Result<Vec<std::path::PathBuf>> {
let mut found = Vec::new();
for entry in std::fs::read_dir(root)? {
let child = entry?.path();
let meta = std::fs::symlink_metadata(&child)?;
if meta.is_dir() {
found.extend(tree_has_special_files(&child)?);
} else if !meta.is_file() {
found.push(child);
}
}
Ok(found)
} Type guard
fn is_special_entry(path: &Path) -> bool {
match std::fs::symlink_metadata(path) {
Ok(m) => !m.is_dir() && !m.is_file(),
Err(_) => false,
}
} Try / catch
match retire_legacy_source_tree(&path) {
Err(e) if e.to_string().contains("special file") => {
// remove the fifo/socket/device node, then retry retirement
}
other => other?,
} Prevention
- Configure daemons to place sockets/FIFOs outside the state directory
- Scan state trees with stat/find for non-regular entries before migration
- Keep restore tooling from extracting device nodes or fifos into state paths
When it happens
Trigger: validate_legacy_tree recursion hits a child whose symlink_metadata shows it is not a symlink, not a directory, and not a file — a FIFO left by a tool, a unix socket created by a process using the state dir, a device node from a bad restore, or a race that swapped the entry type mid-walk.
Common situations: A process (e.g. an embedded daemon) created a socket/FIFO inside the legacy state directory; corrupted or partial backup restores containing special files; tmpfs or devtooling artifacts; tests that leaked fifos into the state path.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- inspect capsule projection
- inspect projected file
- legacy state source changed type
- legacy state source contains a redirect
- legacy state source is not a directory
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/d7bf9cf2dd80a816.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-core/src/dirs_layout_retirement.rs:78
let child_metadata = std::fs::symlink_metadata(&child)?;
if child_metadata.file_type().is_symlink() {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy state source contains a redirect: {}",
child.display()
),
));
}
ensure_legacy_tree_boundary(&child, root_device, &child_metadata)?;
if child_metadata.is_dir() {
validate_legacy_tree(&child, root_device)?;
} else if child_metadata.is_file() {
// Opening only after the no-follow validation ensures a replaced
// symlink is rejected rather than read or removed through it.
crate::platform_fs::verify_no_redirects(&child)?;
} else {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!(
"legacy state source contains a special file: {}",
child.display()
),
));
}
}
Ok(())
}
pub(super) fn delete_legacy_tree(path: &Path, root_device: u64) -> io::Result<()> {
let metadata = match std::fs::symlink_metadata(path) {
Ok(metadata) => metadata,
Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),
Err(error) => return Err(error),
};
if metadata.file_type().is_symlink() || !metadata.is_dir() {View on GitHub (pinned to affd8760f4)