{"record":{"id":"d7bf9cf2dd80a816","repo":"astrid-runtime/astrid","slug":"legacy-state-source-contains-a-special-file","errorCode":null,"errorMessage":"legacy state source contains a special file: {}","messagePattern":"legacy state source contains a special file: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/dirs_layout_retirement.rs","lineNumber":78,"sourceCode":"        let child_metadata = std::fs::symlink_metadata(&child)?;\n        if child_metadata.file_type().is_symlink() {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"legacy state source contains a redirect: {}\",\n                    child.display()\n                ),\n            ));\n        }\n        ensure_legacy_tree_boundary(&child, root_device, &child_metadata)?;\n        if child_metadata.is_dir() {\n            validate_legacy_tree(&child, root_device)?;\n        } else if child_metadata.is_file() {\n            // Opening only after the no-follow validation ensures a replaced\n            // symlink is rejected rather than read or removed through it.\n            crate::platform_fs::verify_no_redirects(&child)?;\n        } else {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"legacy state source contains a special file: {}\",\n                    child.display()\n                ),\n            ));\n        }\n    }\n    Ok(())\n}\n\npub(super) fn delete_legacy_tree(path: &Path, root_device: u64) -> io::Result<()> {\n    let metadata = match std::fs::symlink_metadata(path) {\n        Ok(metadata) => metadata,\n        Err(error) if error.kind() == io::ErrorKind::NotFound => return Ok(()),\n        Err(error) => return Err(error),\n    };\n    if metadata.file_type().is_symlink() || !metadata.is_dir() {","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/dirs_layout_retirement.rs#L60-L96","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before: a fifo/socket inside the legacy tree\n/srv/astrid/var/state/surrealkv/control.sock (socket)\n# after: remove the node and re-run\nrm /srv/astrid/var/state/surrealkv/control.sock\n# restart the daemon with its socket path outside the state tree","handlingStrategy":"validation","validationCode":"fn tree_has_special_files(root: &Path) -> std::io::Result<Vec<std::path::PathBuf>> {\n    let mut found = Vec::new();\n    for entry in std::fs::read_dir(root)? {\n        let child = entry?.path();\n        let meta = std::fs::symlink_metadata(&child)?;\n        if meta.is_dir() {\n            found.extend(tree_has_special_files(&child)?);\n        } else if !meta.is_file() {\n            found.push(child);\n        }\n    }\n    Ok(found)\n}","typeGuard":"fn is_special_entry(path: &Path) -> bool {\n    match std::fs::symlink_metadata(path) {\n        Ok(m) => !m.is_dir() && !m.is_file(),\n        Err(_) => false,\n    }\n}","tryCatchPattern":"match retire_legacy_source_tree(&path) {\n    Err(e) if e.to_string().contains(\"special file\") => {\n        // remove the fifo/socket/device node, then retry retirement\n    }\n    other => other?,\n}","preventionTips":["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"],"tags":["rust","io","filesystem","special-file"],"backgroundTag":"invalid-argument-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}