{"record":{"id":"d379e9df527a81b7","repo":"astrid-runtime/astrid","slug":"read-materialized-capsule-authority-error","errorCode":null,"errorMessage":"read materialized capsule authority: {error:#}","messagePattern":"read materialized capsule authority: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-kernel/src/capsule_materialization.rs","lineNumber":49,"sourceCode":"            anyhow::bail!(\"materialized capsule snapshot differs from the caller's publication\");\n        }\n        if verified.manifest().package.name != manifest.package.name\n            || verified.manifest().package.version != manifest.package.version\n        {\n            anyhow::bail!(\"materialized capsule manifest differs from durable registry\");\n        }\n        let manifest_bytes = Self::read_projection_file_nofollow(&dir.join(\"Capsule.toml\"))\n            .map_err(|error| anyhow::anyhow!(\"read materialized capsule manifest: {error:#}\"))?;\n        if manifest_bytes != verified.manifest_bytes() {\n            anyhow::bail!(\"durable capsule manifest bytes do not match materialization\");\n        }\n        let metadata_bytes = Self::read_projection_file_nofollow(&dir.join(\"meta.json\"))\n            .map_err(|error| anyhow::anyhow!(\"read materialized capsule metadata: {error:#}\"))?;\n        if metadata_bytes != verified.metadata_bytes() {\n            anyhow::bail!(\"durable capsule metadata does not match materialization\");\n        }\n        let authority_bytes = Self::read_projection_file_nofollow(&dir.join(\"authority.json\"))\n            .map_err(|error| anyhow::anyhow!(\"read materialized capsule authority: {error:#}\"))?;\n        if authority_bytes != verified.snapshot().package().authority {\n            anyhow::bail!(\"durable capsule authority bytes do not match materialization\");\n        }\n        let mut expected_files = verified\n            .archive_entries()\n            .map(|(path, bytes)| (path.to_owned(), bytes.to_vec()))\n            .collect::<std::collections::BTreeMap<_, _>>();\n        expected_files.insert(\n            \"Capsule.toml\".to_owned(),\n            verified.manifest_bytes().to_vec(),\n        );\n        expected_files.insert(\"meta.json\".to_owned(), verified.metadata_bytes().to_vec());\n        expected_files.insert(\n            \"authority.json\".to_owned(),\n            verified.snapshot().package().authority.clone(),\n        );\n        let actual = Self::inventory_projection_files(dir)?;\n        if actual.files","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-kernel/src/capsule_materialization.rs#L31-L67","documentation":"During verification of a published capsule materialization, the kernel re-reads the projected authority.json file with read_projection_file_nofollow and wraps any I/O failure with this message. The library throws it because authority.json is the durable record of the capsule's approved authority; if it cannot be read, the kernel cannot prove the materialized capsule does not exceed its installed authority. As with the sibling errors, this is an I/O wrapper — a content mismatch yields the distinct 'durable capsule authority bytes do not match materialization' error.","triggerScenarios":"verify_published_materialization (via repair_published_materialization, confirm_published_materialization, or verify_registry_materialization) reaches the authority.json check while <materialization_dir>/authority.json is missing, unreadable, is a symlink (nofollow open refuses), or is not readable by the current user/UID.","commonSituations":"Interrupted materialization left authority.json absent; the cache directory was partially cleaned by a temp cleaner or manual rm; a symlink or hardened permissions block the read; concurrent repair races removed the directory between checks; network filesystem hiccup.","solutions":["Remove the stale/partial materialization and re-materialize: call repair_published_materialization or ensure_published_materialization so the projection is rebuilt from the durable snapshot.","Verify authority.json exists, is a regular file, and is readable: ls -la <dir>/authority.json; restore permissions if needed (chown/chmod).","Ensure nothing concurrently deletes or replaces the cache directory during verification (hold the activation lock / avoid parallel capsule operations).","Re-publish the capsule if the durable registry copy itself is suspect."],"exampleFix":"// before: confirming a possibly torn cache\nkernel.confirm_published_materialization(&dir, &principal, &manifest, &snapshot)?;\n\n// after: let repair rebuild the projection when verification fails\nif kernel.confirm_published_materialization(&dir, &principal, &manifest, &snapshot).is_err() {\n    kernel.ensure_published_materialization(&dir, &principal, &manifest, &snapshot)?;\n}","handlingStrategy":"validation","validationCode":"fn authority_projection_readable(dir: &std::path::Path) -> Result<(), String> {\n    let p = dir.join(\"authority.json\");\n    let md = std::fs::symlink_metadata(&p)\n        .map_err(|e| format!(\"authority.json unreadable: {e}\"))?;\n    if md.file_type().is_symlink() { return Err(\"authority.json is a symlink\".into()); }\n    if !md.is_file() { return Err(\"authority.json is not a regular file\".into()); }\n    std::fs::File::open(&p).map_err(|e| format!(\"authority.json open failed: {e}\"))?;\n    Ok(())\n}","typeGuard":"fn has_regular_file(dir: &std::path::Path, name: &str) -> bool {\n    std::fs::symlink_metadata(dir.join(name))\n        .map(|md| md.is_file())\n        .unwrap_or(false)\n}","tryCatchPattern":"if let Err(e) = kernel.confirm_published_materialization(&dir, &principal, &manifest, &snapshot) {\n    if e.to_string().contains(\"read materialized capsule authority\") {\n        let _ = std::fs::remove_dir_all(&dir);\n        kernel.ensure_published_materialization(&dir, &principal, &manifest, &snapshot)?;\n    } else { return Err(e); }\n}","preventionTips":["Treat authority.json as kernel-owned: never move, symlink, or hand-edit it.","Hold activation locks and avoid running parallel capsule operations against the same cache dir.","Ensure the materialization completes fully (no SIGKILL mid-extract); re-run repair after any crash.","Monitor cache dirs for unexpected symlinks — the nofollow reads intentionally reject them."],"tags":["io","filesystem","capsule","materialization","security"],"backgroundTag":"file-read-failed","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"}