can1357/oh-my-pi · error · ArchiveError
Failed to read tar archive
Error message
Failed to read tar archive
What it means
readTar reads the entire archive source into memory before parsing. If readAllBytes throws a non-ArchiveError (stream I/O failure, decode error, etc.), it is wrapped in this generic ArchiveError so callers only need to catch one type. The underlying cause message is preserved when the original error is an Error instance.
Source
Thrown at packages/utils/src/ar/tar.ts:586
mtimeMs,
mode,
storage: { type: "member", source: new TarMemberSource(buffer, dataOffset, sparse) },
});
}
if (!sawTerminator) throw new ArchiveError("Not a valid tar archive: missing terminating zero block");
resolvePendingLinks(entries, pendingLinks, limits);
return [...entries.values()];
}
/** Read and index a tar source after one bounded whole-stream read. */
export const readTar: FormatReader = async (source, options) => {
assertInMemorySize(source.size, options.limits);
let bytes: Uint8Array;
try {
bytes = await readAllBytes(source);
} catch (error) {
if (error instanceof ArchiveError) throw error;
throw new ArchiveError(error instanceof Error ? error.message : "Failed to read tar archive");
}
if (bytes.byteLength !== source.size) throw new ArchiveError("Invalid archive: truncated data");
return readTarEntriesFromBuffer(bytes, options);
};
/** Detect a tar header, including legacy pre-ustar archives, by its checksum. */
export function sniffTar(bytes: Uint8Array): boolean {
if (bytes.byteLength < BLOCK_SIZE) return false;
if (isZeroBlock(bytes, 0)) return true;
try {
if (readTarString(bytes, NAME_OFFSET, NAME_LENGTH).length === 0) return false;
const size = readTarSize(bytes, SIZE_OFFSET);
return Number.isSafeInteger(paddedSize(size)) && checksumMatches(bytes, 0);
} catch {
return false;
}
}
View on GitHub (pinned to 9690622007)
Solutions
- Inspect the wrapped message (or the original console/log) for the real I/O cause and fix that first
- Verify the file/source is readable and unchanged before calling readTar
- Re-download or re-open the archive; retry only if the cause was transient (network)
- If you supply a custom source, ensure its read/byte-returning contract never rejects except on real failures
Example fix
// before: source may be a dying stream
await readTar({ stream: resp.body, ... });
// after: buffer to a stable file first, then read
await Bun.write(tmp, resp);
await readTar({ size: tmp.size, bytes: await Bun.file(tmp).bytes(), ... }); Defensive patterns
Strategy: try-catch
Validate before calling
const stat = await fs.stat(path);
if (!stat.isFile()) throw new Error("not a readable regular file"); Type guard
function isArchiveError(err: unknown): err is ArchiveError {
return err instanceof ArchiveError;
} Try / catch
try {
return await readTar(source, options);
} catch (err) {
if (err instanceof ArchiveError && err.message === "Failed to read tar archive") {
// underlying I/O failed: check disk, permissions, or stream state
}
throw err;
} Prevention
- Copy network streams to a local file before parsing
- Keep a stable reference to the file — avoid reading files being rotated/deleted
- Wrap custom source read() implementations so they throw ArchiveError with the real cause
When it happens
Trigger: Passing a source whose underlying stream/socket/file fails during readAllBytes — closed file descriptor, EACCES on an opened-but-revoked file, network stream reset mid-read, or a source reader that throws a non-Archive error.
Common situations: Reading a tar from an HTTP response whose connection dropped, reading from a file deleted or permission-revoked between open and read, custom source implementations whose read() rejects, disk I/O errors.
Related errors
- underlying bytestream error: {}
- Failed to read ASAR member '${formatArchivePathForError(memb
- ${error instanceof Error ? error.message : String(error)}
- Computed edit range is out of bounds
- I/O error occurred
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/9b95c2964cde2b04.
Report an issue: GitHub.