{"record":{"id":"76c574c13c527978","repo":"astrid-runtime/astrid","slug":"layout-migration-source-contains-a-special-file","errorCode":null,"errorMessage":"layout migration source contains a special file: {}","messagePattern":"layout migration source contains a special file: (.+?)","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/astrid-core/src/dirs_layout_records.rs","lineNumber":447,"sourceCode":"                *bytes = bytes\n                    .checked_add(read as u64)\n                    .ok_or_else(|| io::Error::other(\"layout inventory byte count overflow\"))?;\n                file_bytes = file_bytes\n                    .checked_add(read as u64)\n                    .ok_or_else(|| io::Error::other(\"layout inventory file length overflow\"))?;\n                hasher.update(&buffer[..read]);\n            }\n            if file_bytes != metadata.len() {\n                return Err(io::Error::new(\n                    io::ErrorKind::InvalidData,\n                    format!(\n                        \"layout migration source changed while inventoried: {}\",\n                        child_path.display()\n                    ),\n                ));\n            }\n        } else {\n            return Err(io::Error::new(\n                io::ErrorKind::InvalidData,\n                format!(\n                    \"layout migration source contains a special file: {}\",\n                    child_path.display()\n                ),\n            ));\n        }\n    }\n    Ok(())\n}\n\nfn hash_inventory_field(hasher: &mut blake3::Hasher, label: &[u8], value: &[u8]) {\n    hasher.update(&(label.len() as u64).to_le_bytes());\n    hasher.update(label);\n    hasher.update(&(value.len() as u64).to_le_bytes());\n    hasher.update(value);\n}\n","sourceCodeStart":429,"sourceCodeEnd":465,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-core/src/dirs_layout_records.rs#L429-L465","documentation":"The inventory walk only supports plain files and directories inside the migration source. Any other directory entry type (fifo, socket, device node, etc.) makes the tree impossible to fingerprint deterministically, so inventory_directory aborts with InvalidData naming the path. This keeps the migration inventory well-defined across platforms.","triggerScenarios":"inventory_directory encounters a child whose symlink_metadata shows it is neither a directory nor a regular file (e.g. a Unix fifo, unix socket, or device node) inside the state tree.","commonSituations":"A database/runtime left a unix socket file in the state directory; a test or dev script created named pipes there; someone mounted a device node into the tree.","solutions":["Stop the application that created the special file (usually a daemon holding a unix socket) so it is cleaned up.","Delete the named fifo/socket/device node if it is stale (it will be recreated on next run).","Verify no device nodes exist: find <state-dir> ! -type f ! -type d and remove/fix the hits.","Re-run the migration once the tree holds only regular files and directories."],"exampleFix":"// before: stale socket blocks migration\n$ ls ~/.local/state/astrid/surrealkv.sock   # srwxr-xr-x unix socket\n// after: stop the daemon and remove it\n$ systemctl --user stop astrid && rm ~/.local/state/astrid/surrealkv.sock && astrid migrate","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn assert_only_files_and_dirs(dir: &Path) -> std::io::Result<()> {\n    for entry in std::fs::read_dir(dir)? {\n        let entry = entry?;\n        let ft = std::fs::symlink_metadata(entry.path())?.file_type();\n        if !(ft.is_file() || ft.is_dir()) {\n            return Err(std::io::Error::new(\n                std::io::ErrorKind::InvalidData,\n                format!(\"special file in state tree: {}\", entry.path().display()),\n            ));\n        }\n        if ft.is_dir() {\n            assert_only_files_and_dirs(&entry.path())?;\n        }\n    }\n    Ok(())\n}","typeGuard":"fn is_regular_or_dir(p: &Path) -> bool {\n    std::fs::symlink_metadata(p)\n        .map(|m| m.file_type().is_file() || m.file_type().is_dir())\n        .unwrap_or(false)\n}","tryCatchPattern":null,"preventionTips":["Stop daemons that create unix sockets/fifos inside the state directory before migrating.","Scan for special files first: find <state-dir> ! -type f ! -type d.","Keep runtime sockets outside the persisted state tree."],"tags":["filesystem","special-file","migration","unix"],"backgroundTag":"incompatible-source-type","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}