can1357/oh-my-pi · error · ArchiveError
Archive hard link '${formatArchivePathForError(entry.path)}'
Error message
Archive hard link '${formatArchivePathForError(entry.path)}' targets ${reason} '${formatArchivePathForError(pending.targetPath)}' What it means
Thrown when a tar hard link's target resolves to a path that is not a directory and has no readable file member behind it — either the target member exists but has no readable storage ('unreadable member', e.g. a symlink kept as a raw link) or no member exists at all ('missing member'). Hard links require a concrete file target.
Source
Thrown at packages/utils/src/ar/tar.ts:400
);
}
entry.storage = { type: "link", targetPath: pending.targetPath, resolveTarget: false };
continue;
}
const target = entries.get(targetPath);
if (target?.storage && !target.isDirectory && !unresolved.has(target)) {
entry.size = target.size;
entry.storage = target.storage;
continue;
}
const targetIsDirectory = targetPath === "" || target?.isDirectory === true || directoryPrefixes.has(targetPath);
if (!targetIsDirectory) {
if (pending.kind === "symlink") {
entry.storage = { type: "link", targetPath: pending.targetPath, resolveTarget: false };
continue;
}
const reason = target ? "unreadable member" : "missing member";
throw new ArchiveError(
`Archive hard link '${formatArchivePathForError(entry.path)}' targets ${reason} '${formatArchivePathForError(pending.targetPath)}'`,
);
}
if (pending.kind === "hard link") {
throw new ArchiveError(
`Archive hard link '${formatArchivePathForError(entry.path)}' targets directory '${formatArchivePathForError(pending.targetPath)}'`,
);
}
entry.isDirectory = true;
entry.storage = { type: "link", targetPath: pending.targetPath, resolveTarget: false };
}
if (unresolved.size > 0) throw new ArchiveError("Archive contains cyclic or unsupported links");
}
/** Index an already-decompressed tar buffer with bounded GNU, ustar, and PAX handling. */
export function readTarEntriesFromBuffer(buffer: Uint8Array, options: FormatReadOptions): ArchiveIndexEntry[] {
const { limits } = options;
assertInMemorySize(buffer.byteLength, limits);View on GitHub (pinned to 9690622007)
Solutions
- Check `tar tvf` for the target path named in the message and confirm the file member is present.
- Re-create the archive ensuring hard-link targets are archived as regular files (GNU tar archives targets in full when needed).
- If you control archive generation, emit hard links after their target member, or replace hard links with regular file copies.
Example fix
// before (creating archive): hard link with target omitted tar -cf out.tar link-only-dir/ // after: include the target file or dereference links tar -cf out.tar -h dir/
Defensive patterns
Strategy: validation
Validate before calling
// Verify with system tar before indexing that all hardlink targets exist // $ tar -tvf archive.tar | review typeflag-1 entries and their targets
Try / catch
try {
await readTar(bytes, opts);
} catch (e) {
if (e instanceof ArchiveError && e.message.includes("targets unreadable member") ||
e instanceof ArchiveError && e.message.includes("targets missing member")) {
throw new Error("Archive hard link points at a missing/unreadable member; re-create archive");
}
throw e;
} Prevention
- Create archives so hard-link targets are included as regular file members.
- Emit hard links after their target member in the archive stream.
- Use `tar -h` to dereference links when portability matters more than space.
When it happens
Trigger: readTar on an archive with a typeflag-'1' entry whose linkname points at a path absent from the index, or at a member whose storage cannot be shared (e.g. a dangling symlink target).
Common situations: Archives extracted/re-packed lossily so the hard-link target file was dropped; tools emitting hard links before their target member; hand-crafted archives.
Related errors
- Archive hard link '${formatArchivePathForError(entry.path)}'
- Archive hard link '${formatArchivePathForError(entry.path)}'
- Invalid tar octal value: ${value}
- Truncated embedded addon archive entry: ${filename}
- Unsafe embedded addon archive entry: ${filename}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ccc687f678fd38a6.
Report an issue: GitHub.