{"record":{"id":"075f81cf5178058b","repo":"astrid-runtime/astrid","slug":"opaque-asset-path-must-be-a-directory","errorCode":null,"errorMessage":"opaque asset path must be a directory: {}","messagePattern":"opaque asset path must be a directory: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-build/src/archiver.rs","lineNumber":39,"sourceCode":"    let mut files = Vec::new();\n    for name in OPAQUE_ASSET_DIRS {\n        let root = base_dir.join(name);\n        let metadata = match fs::symlink_metadata(&root) {\n            Ok(metadata) => metadata,\n            Err(error) if error.kind() == std::io::ErrorKind::NotFound => continue,\n            Err(error) => {\n                return Err(error)\n                    .with_context(|| format!(\"Failed to inspect asset path: {}\", root.display()));\n            },\n        };\n        if metadata.file_type().is_symlink() {\n            anyhow::bail!(\n                \"opaque capsule asset directories cannot be symlinks: {}\",\n                root.display()\n            );\n        }\n        if !metadata.is_dir() {\n            anyhow::bail!(\"opaque asset path must be a directory: {}\", root.display());\n        }\n        let mut pending = vec![root];\n        while let Some(dir) = pending.pop() {\n            for entry in fs::read_dir(&dir)\n                .with_context(|| format!(\"Failed to read asset directory: {}\", dir.display()))?\n            {\n                let entry = entry?;\n                let path = entry.path();\n                let file_type = entry.file_type()?;\n                if file_type.is_symlink() {\n                    anyhow::bail!(\n                        \"opaque capsule assets cannot be symlinks: {}\",\n                        path.display()\n                    );\n                }\n                if file_type.is_dir() {\n                    pending.push(path);\n                } else if file_type.is_file() {","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-build/src/archiver.rs#L21-L57","documentation":"The signed channel pointer must name its release metadata asset exactly 'astrid-<version>-release.toml', derived from the pointer's own version. This ensure! fails when metadata_asset diverges from that canonical naming scheme, so the client would fetch a manifest it cannot bind to this pointer.","triggerScenarios":"validate_pointer (via parse_channel or enforce_continuity) sees a ChannelPointer whose release.metadata_asset is not the string format!(\"astrid-{version}-release.toml\") for the canonical version.","commonSituations":"Renamed or vendored manifest asset in a hand-maintained channel file; a tool from an older naming convention; typo in the asset field; pointer regenerated for a different version but asset name left stale.","solutions":["Set release.metadata_asset to exactly \"astrid-<version>-release.toml\" using the canonical version from the pointer.","Regenerate the signed pointer with the release tooling so all derived fields are consistent.","Re-sign and re-upload the pointer, then re-run parse_channel."],"exampleFix":"# before\nversion = \"1.2.3\"\nmetadata_asset = \"astrid-release.toml\"\n# after\nversion = \"1.2.3\"\nmetadata_asset = \"astrid-1.2.3-release.toml\"","handlingStrategy":"validation","validationCode":"fn metadata_asset_ok(version: &str, asset: &str) -> bool {\n    asset == format!(\"astrid-{version}-release.toml\")\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = parse_channel(&bytes, channel, now) {\n    if e.to_string().contains(\"metadata asset is invalid\") { /* fix asset name and re-sign */ }\n    return Err(e.into());\n}","preventionTips":["Derive metadata_asset from the version programmatically","Lint derived fields before signing","Regenerate pointers with tooling, not by hand"],"tags":["validation","signing","naming"],"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-14T05:17:10.506Z"}