astrid-runtime/astrid · error
durable capsule archive contains duplicate directory path
Error message
durable capsule archive contains duplicate directory path
What it means
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.
Source
Thrown at crates/astrid-capsule-install/src/storage.rs:389
{
bail!("durable capsule archive contains unsafe path");
}
let entry_type = entry.header().entry_type();
if !entry_type.is_dir() && !entry_type.is_file() {
bail!("durable capsule archive contains a link or special file");
}
let name = path
.to_str()
.ok_or_else(|| anyhow::anyhow!("durable capsule archive path is not UTF-8"))?
.replace('\\', "/");
if files.contains_key(&name) || directories.contains(&name) {
bail!("durable capsule archive contains duplicate path {name}");
}
if entry_type.is_dir() {
if !directories.insert(name) {
bail!("durable capsule archive contains duplicate directory path");
}
continue;
}
let mut bytes = Vec::new();
entry
.read_to_end(&mut bytes)
.with_context(|| format!("read durable capsule archive file {name}"))?;
files.insert(name, bytes);
}
Ok(ArchiveInventory { files, directories })
}
/// Publish one source directory into the target principal's durable registry.
///
/// The source tree is canonicalized to a deterministic gzip/tar archive. The
/// package is committed as one content batch; a failed publication therefore
/// leaves the prior package authoritative. Existing durable content is used asView on GitHub (pinned to affd8760f4)
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.
Example fix
// before: duplicate dir entries from concatenation
// cat part1.tgz part2.tgz > capsule.tgz (both include "assets/")
// after: emit each dir once during build
if directories_seen.insert(dir_name.to_string()) { write_dir_entry(dir_name); } Defensive patterns
Strategy: validation
Validate before calling
let mut dirs = std::collections::BTreeSet::new();
if entry_type.is_dir() && !dirs.insert(name.clone()) {
return Err(format!("duplicate directory entry {name}"));
} Type guard
fn directory_entries_unique(dirs: &[String]) -> bool {
dirs.iter().collect::<std::collections::BTreeSet<_>>().len() == dirs.len()
} Try / catch
match read_verified_durable_package_for_owner(&store, owner, id).await {
Ok(pkg) => pkg,
Err(e) if e.to_string().contains("duplicate directory path") => {
// regenerate the archive emitting each directory once
},
Err(e) => return Err(e),
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Understand the failure class
Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.
Related errors
- durable capsule archive contains duplicate path {name}
- capsule archive contains duplicate path {name}
- capsule archive contains an unsafe path {}
- capsule archive contains a link or special file {name}
- durable capsule archive contains unsafe path
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/08448067cc931086.
Report an issue: GitHub.