{"record":{"id":"ca4dbd8e73689873","repo":"astrid-runtime/astrid","slug":"read-capsule-projection-error","errorCode":null,"errorMessage":"read capsule projection {}: {error}","messagePattern":"read capsule projection (.+?): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/lib.rs","lineNumber":1624,"sourceCode":"        let digest = blake3::hash(&snapshot.package().archive)\n            .to_hex()\n            .to_string();\n        if components[2] != digest {\n            anyhow::bail!(\"materialized capsule digest does not match durable registry\");\n        }\n        Ok(())\n    }\n\n    /// Inventory a projection without traversing redirects or special files.\n    #[cfg(not(all(target_arch = \"wasm32\", target_os = \"unknown\")))]\n    fn inventory_projection_files(root: &Path) -> anyhow::Result<ProjectionInventory> {\n        fn walk(\n            root: &Path,\n            directory: &Path,\n            inventory: &mut ProjectionInventory,\n        ) -> anyhow::Result<()> {\n            for entry in std::fs::read_dir(directory).map_err(|error| {\n                anyhow::anyhow!(\"read capsule projection {}: {error}\", directory.display())\n            })? {\n                let entry = entry\n                    .map_err(|error| anyhow::anyhow!(\"read capsule projection entry: {error}\"))?;\n                let path = entry.path();\n                let relative = path.strip_prefix(root).map_err(|_| {\n                    anyhow::anyhow!(\"capsule projection escaped its root: {}\", path.display())\n                })?;\n                let relative_text = relative.to_str().ok_or_else(|| {\n                    anyhow::anyhow!(\"capsule projection path is not UTF-8: {}\", path.display())\n                })?;\n                let metadata = std::fs::symlink_metadata(&path).map_err(|error| {\n                    anyhow::anyhow!(\"inspect capsule projection {}: {error}\", path.display())\n                })?;\n                let file_type = metadata.file_type();\n                if file_type.is_symlink() {\n                    anyhow::bail!(\n                        \"capsule projection contains a symbolic link: {}\",\n                        path.display()","sourceCodeStart":1606,"sourceCodeEnd":1642,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/lib.rs#L1606-L1642","documentation":"Thrown by the projection inventory `walk` helper when `std::fs::read_dir` on a capsule projection directory fails. The directory could not be listed at all, so the inventory cannot be built. The OS error is wrapped with the directory path for diagnosis.","triggerScenarios":"Calling the projection inventory/walk code against a directory path that does not exist, is not a directory, or is unreadable due to permissions.","commonSituations":"Projection root deleted or not yet materialized before walking; wrong mount path in config; permission changes on the projection directory; passing a file path instead of a directory.","solutions":["Ensure the projection directory exists and is materialized before invoking the inventory walk.","Check filesystem permissions on the directory (read/execute bits).","Confirm the configured projection root path is correct and is a directory.","Inspect the wrapped io::Error source for the exact OS reason (ENOENT, EACCES, ENOTDIR)."],"exampleFix":"// before\ninventory::walk(&root, &root, &mut inv)?; // fails if root missing\n// after\nassert!(root.is_dir(), \"projection root must exist: {}\", root.display());\ninventory::walk(&root, &root, &mut inv)?;","handlingStrategy":"validation","validationCode":"if !dir.is_dir() {\n    anyhow::bail!(\"projection directory missing: {}\", dir.display());\n}","typeGuard":"fn is_listable_dir(p: &Path) -> bool { p.is_dir() && std::fs::read_dir(p).is_ok() }","tryCatchPattern":"match walk_inventory(root) {\n    Err(e) if e.to_string().contains(\"read capsule projection\") => retry_or_rematerialize(root),\n    Err(e) => return Err(e),\n    Ok(inv) => Ok(inv),\n}","preventionTips":["Materialize the projection root before walking.","Verify configured paths point at directories, not files.","Check permissions after deployment or container image changes."],"tags":["filesystem","io","rust","directory"],"backgroundTag":"directory-not-found","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}