can1357/oh-my-pi · error · ArchiveError

Invalid or corrupt tar archive header

Error message

Invalid or corrupt tar archive header

What it means

Thrown when a 512-byte tar block's stored checksum does not match the computed unsigned or signed byte sum of the header. The library validates every non-zero header block before parsing, so any bit corruption or non-tar data in the stream fails here.

Source

Thrown at packages/utils/src/ar/tar.ts:441

		const indexed = upsertArchiveEntry(entries, entry);
		if (!indexed) return;
		if (existing) pendingLinks.delete(existing);
		if (pendingLink) pendingLinks.set(indexed, pendingLink);
		assertEntryCount(entries.size, limits);
	};
	let offset = 0;
	let longName: string | undefined;
	let longLink: string | undefined;
	let localPax: Map<string, string> | undefined;
	const globalPax = new Map<string, string>();
	let sawTerminator = false;

	while (offset + BLOCK_SIZE <= buffer.byteLength) {
		if (isZeroBlock(buffer, offset)) {
			sawTerminator = true;
			break;
		}
		if (!checksumMatches(buffer, offset)) throw new ArchiveError("Invalid or corrupt tar archive header");
		const headerOffset = offset;
		const typeFlag = String.fromCharCode(buffer[headerOffset + TYPEFLAG_OFFSET] || 0x30);
		let size = readTarSize(buffer, headerOffset + SIZE_OFFSET);
		let name = readTarString(buffer, headerOffset + NAME_OFFSET, NAME_LENGTH);
		if (isUstarHeader(buffer, headerOffset)) {
			const prefix = readTarString(buffer, headerOffset + PREFIX_OFFSET, PREFIX_LENGTH);
			if (prefix) name = `${prefix}/${name}`;
		}
		let linkName = readTarString(buffer, headerOffset + LINKNAME_OFFSET, LINKNAME_LENGTH);
		const mtime = readTarNumeric(buffer, headerOffset + MTIME_OFFSET, MTIME_LENGTH);
		const rawMode = readTarNumeric(buffer, headerOffset + MODE_OFFSET, MODE_LENGTH);
		const mode = Number.isSafeInteger(rawMode) && rawMode >= 0 ? rawMode : undefined;
		offset += BLOCK_SIZE;
		const dataBlocks = paddedSize(size);
		if (dataBlocks > buffer.byteLength - offset) throw new ArchiveError("Archive member data is truncated");
		const data = buffer.subarray(offset, offset + size);

		if (typeFlag === "L") {

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify you decompressed first: gunzip .tar.gz/.tgz before passing bytes, or use the composite reader that sniffs compression.
  2. Verify the file with `tar tf archive.tar` or `gzip -t` to confirm integrity; re-download if corrupt.
  3. Check you are reading the correct file/offset (e.g. not an inner slice of a larger file).
  4. Sniff format before parsing (the library's sniffTar exists for this) and route non-tar input to the right reader.

Example fix

// before: raw gzipped bytes into tar reader
const bytes = await Bun.file("archive.tgz").bytes();
await readTar(bytes, opts); // checksum failure
// after: decompress first
const { gunzipSync } = await import("node:zlib");
const bytes = gunzipSync(await Bun.file("archive.tgz").bytes());
await readTar(bytes, opts);
Defensive patterns

Strategy: validation

Validate before calling

import { sniffTar } from "@oh-my-pi/pi-utils/ar/tar";
const raw = await Bun.file(path).bytes();
// Decompress if gzipped before handing bytes to the tar reader
const isGzip = raw[0] === 0x1f && raw[1] === 0x8b;
const bytes = isGzip ? gunzipSync(raw) : raw;
if (!sniffTar(bytes)) throw new Error(`${path} is not a tar archive`);

Type guard

function isGzipBytes(b: Uint8Array): boolean {
  return b.length >= 2 && b[0] === 0x1f && b[1] === 0x8b;
}

Try / catch

try {
  await readTar(bytes, opts);
} catch (e) {
  if (e instanceof ArchiveError && e.message === "Invalid or corrupt tar archive header") {
    throw new Error("Not a valid (uncompressed) tar stream — decompress or re-download");
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling readTar/readTarEntriesFromBuffer on data whose header checksum fails: truncated/corrupted downloads, files that are not actually tar (e.g. wrong decompression — a gzip served as plain tar), or concatenation damage mid-archive.

Common situations: Forgetting to decompress (.tar.gz passed directly to a plain tar reader), partial HTTP downloads, transferring archives in text mode, or reading the wrong file/offset.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/2354e6af3224a566. Report an issue: GitHub.