{"record":{"id":"08448067cc931086","repo":"astrid-runtime/astrid","slug":"durable-capsule-archive-contains-duplicate-directo","errorCode":null,"errorMessage":"durable capsule archive contains duplicate directory path","messagePattern":"durable capsule archive contains duplicate directory path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-capsule-install/src/storage.rs","lineNumber":389,"sourceCode":"        {\n            bail!(\"durable capsule archive contains unsafe path\");\n        }\n\n        let entry_type = entry.header().entry_type();\n        if !entry_type.is_dir() && !entry_type.is_file() {\n            bail!(\"durable capsule archive contains a link or special file\");\n        }\n\n        let name = path\n            .to_str()\n            .ok_or_else(|| anyhow::anyhow!(\"durable capsule archive path is not UTF-8\"))?\n            .replace('\\\\', \"/\");\n        if files.contains_key(&name) || directories.contains(&name) {\n            bail!(\"durable capsule archive contains duplicate path {name}\");\n        }\n        if entry_type.is_dir() {\n            if !directories.insert(name) {\n                bail!(\"durable capsule archive contains duplicate directory path\");\n            }\n            continue;\n        }\n\n        let mut bytes = Vec::new();\n        entry\n            .read_to_end(&mut bytes)\n            .with_context(|| format!(\"read durable capsule archive file {name}\"))?;\n        files.insert(name, bytes);\n    }\n    Ok(ArchiveInventory { files, directories })\n}\n\n/// Publish one source directory into the target principal's durable registry.\n///\n/// The source tree is canonicalized to a deterministic gzip/tar archive. The\n/// package is committed as one content batch; a failed publication therefore\n/// leaves the prior package authoritative. Existing durable content is used as","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-capsule-install/src/storage.rs#L371-L407","documentation":"A second directory entry resolved to a directory path already recorded in the directory set. read_archive_files keeps directories in a BTreeSet solely to detect this; a repeated directory path means the archive was assembled inconsistently, so it is rejected.","triggerScenarios":"read_archive_files when two entries are directories with the same normalized name, so directories.insert(name) returns false after the earlier files/directories containment check passed.","commonSituations":"Merged/concatenated tar archives; archive builders emitting explicit directory entries multiple times; archives generated from overlapping source directories (e.g. '.' included twice via different prefixes).","solutions":["Rebuild the archive emitting each directory at most once.","Deduplicate directory entries during archive creation with a seen-set.","Regenerate the archive from a single canonical source directory instead of concatenating tars.","Locate the duplicated directory entry with tar -tf and fix the packaging script."],"exampleFix":"// before: duplicate dir entries from concatenation\n// cat part1.tgz part2.tgz > capsule.tgz (both include \"assets/\")\n// after: emit each dir once during build\nif directories_seen.insert(dir_name.to_string()) { write_dir_entry(dir_name); }","handlingStrategy":"validation","validationCode":"let mut dirs = std::collections::BTreeSet::new();\nif entry_type.is_dir() && !dirs.insert(name.clone()) {\n    return Err(format!(\"duplicate directory entry {name}\"));\n}","typeGuard":"fn directory_entries_unique(dirs: &[String]) -> bool {\n    dirs.iter().collect::<std::collections::BTreeSet<_>>().len() == dirs.len()\n}","tryCatchPattern":"match read_verified_durable_package_for_owner(&store, owner, id).await {\n    Ok(pkg) => pkg,\n    Err(e) if e.to_string().contains(\"duplicate directory path\") => {\n        // regenerate the archive emitting each directory once\n    },\n    Err(e) => return Err(e),\n}","preventionTips":["Emit explicit directory entries at most once per archive.","Never build capsule archives by concatenating multiple tars.","Run tar -tf | sort | uniq -d as a packaging-time check."],"tags":["archive","tar","duplicate","validation"],"backgroundTag":"file-already-exists","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"}