can1357/oh-my-pi · error · ArchiveError
Duplicate tar member path '${formatArchivePathForError(norma
Error message
Duplicate tar member path '${formatArchivePathForError(normalized)}' What it means
The members map resolved to the same normalized path twice with incompatible intent (two files, a file and a directory, or a duplicate directory that isn't idempotent-mergeable). Tar archives cannot contain two members with the same name, so the encoder throws with the formatted path.
Source
Thrown at packages/utils/src/ar/tar.ts:764
const pathBytes = TEXT_ENCODER.encode(normalized);
if (pathBytes.byteLength === 0) throw new ArchiveError("Invalid empty tar member path");
if (directory && bytes.byteLength !== 0) {
throw new ArchiveError(`Tar directory '${formatArchivePathForError(normalized)}' cannot contain file data`);
}
const segments = normalized.split("/");
for (let index = 1; index < segments.length; index++) {
const parent = segments.slice(0, index).join("/");
const kind = kinds.get(parent);
if (kind === "file")
throw new ArchiveError(`Tar member '${formatArchivePathForError(parent)}' is not a directory`);
if (kind === "directory") continue;
kinds.set(parent, "directory");
appendTarEntry(parts, parent, new Uint8Array(0), true, sequence++);
}
const existing = kinds.get(normalized);
if (existing) {
if (directory && existing === "directory") continue;
throw new ArchiveError(`Duplicate tar member path '${formatArchivePathForError(normalized)}'`);
}
kinds.set(normalized, directory ? "directory" : "file");
appendTarEntry(parts, normalized, bytes, directory, sequence++);
}
parts.push(new Uint8Array(BLOCK_SIZE * 2));
return concatBytes(parts);
}
View on GitHub (pinned to 9690622007)
Solutions
- Normalize keys yourself and deduplicate the members map before createTar
- Merge duplicate entries by choosing or concatenating content upstream
- Use unique, already-normalized relative paths as keys
Example fix
// before
members.set("./x", a);
members.set("x", b); // normalizes to same path
// after
members.set("x", chooseContent(a, b)); Defensive patterns
Strategy: validation
Validate before calling
const seen = new Set<string>();
for (const key of members.keys()) {
const norm = key.replace(/^\.\//, "").replace(/\/{2,}/g, "/");
if (seen.has(norm)) throw new Error(`Duplicate member path after normalization: '${norm}'`);
seen.add(norm);
} Try / catch
try {
return await createTar(members);
} catch (err) {
if (err instanceof ArchiveError && err.message.startsWith("Duplicate tar member path")) {
// merge or drop duplicates before retrying
}
throw err;
} Prevention
- Normalize keys ('./x' → 'x', collapse '//' ) and dedupe before createTar
- Use a Map keyed by normalized path so duplicates collapse by construction
When it happens
Trigger: Two distinct raw keys normalize to the same path (e.g. './x' and 'x', or 'a//b' and 'a/b'); a directory entry passed twice is tolerated, but any file duplication or dir/file clash throws.
Common situations: Case-insensitive or backslash-sourced listings collapsing to one key; merging archives; a zip importer yielding './' prefixed names.
Related errors
- Tar member '${formatArchivePathForError(parent)}' is not a d
- Invalid tar octal value: ${value}
- Truncated embedded addon archive entry: ${filename}
- Unsafe embedded addon archive entry: ${filename}
- Unsupported embedded addon archive entry type ${typeflag}: $
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/3d0995a23532514e.
Report an issue: GitHub.