can1357/oh-my-pi · error · ArchiveError

Invalid tar ${field}

Error message

Invalid tar ${field}

What it means

parsePaxSize parses a size string taken from a PAX extended-header record ('size', 'GNU.sparse.realsize', etc.). This throw fires when the string is not pure decimal digits — the field name is interpolated into the message, e.g. "Invalid tar member size" or "Invalid tar sparse real size". PAX stores large values as decimal text, so any non-digit means the record is malformed.

Source

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

	}
	return Number(value);
}

function readTarSize(buffer: Uint8Array, offset: number): number {
	const size = readTarNumeric(buffer, offset, SIZE_LENGTH);
	if (!Number.isSafeInteger(size) || size < 0) throw new ArchiveError("Invalid tar member size");
	return size;
}

function paddedSize(size: number): number {
	const remainder = size % BLOCK_SIZE;
	const padded = size + (remainder === 0 ? 0 : BLOCK_SIZE - remainder);
	if (!Number.isSafeInteger(padded)) throw new ArchiveError("Invalid tar member size");
	return padded;
}

function parsePaxSize(value: string, field: string): number {
	if (!/^\d+$/.test(value)) throw new ArchiveError(`Invalid tar ${field}`);
	const size = Number(value);
	if (!Number.isSafeInteger(size) || size < 0) throw new ArchiveError(`Invalid tar ${field}`);
	return size;
}

function isZeroBlock(buffer: Uint8Array, offset: number): boolean {
	for (let index = 0; index < BLOCK_SIZE; index++) {
		if (buffer[offset + index] !== 0) return false;
	}
	return true;
}

function checksumMatches(buffer: Uint8Array, offset: number): boolean {
	const stored = readTarNumeric(buffer, offset + CHECKSUM_OFFSET, CHECKSUM_LENGTH);
	let unsigned = 0;
	let signed = 0;
	for (let index = 0; index < BLOCK_SIZE; index++) {
		const inChecksum = index >= CHECKSUM_OFFSET && index < CHECKSUM_OFFSET + CHECKSUM_LENGTH;

View on GitHub (pinned to 9690622007)

Solutions

  1. Inspect the PAX record in the archive (tar --to-stdout on the PaxHeaders member) and fix or regenerate the archive.
  2. Ensure the tool that wrote the archive emits PAX numeric values as plain decimal ASCII digits.
  3. Recreate the archive with a standard tar implementation (GNU tar, bsdtar) if a custom writer produced it.
  4. Catch ArchiveError and reject the archive; the parser will not guess at malformed numerics.

Example fix

// before (custom PAX writer)
record = `size=0x${size.toString(16)}\n`;
// after
record = `size=${size.toString(10)}\n`;
Defensive patterns

Strategy: try-catch

Validate before calling

// PAX numeric records must be pure decimal ASCII digits
function isValidPaxNumber(value: string): boolean {
  return /^\d+$/.test(value);
}

Try / catch

try {
  const entries = readTarEntriesFromBuffer(buffer, options);
} catch (err) {
  if (err instanceof ArchiveError && err.message.startsWith("Invalid tar ")) {
    throw new Error(`Archive has a malformed PAX numeric record (${err.message})`);
  }
  throw err;
}

Prevention

When it happens

Trigger: A PAX extended header (typeflag 'x'/'g') contains a size-ish record whose value has non-digit characters — e.g. `size=12abc\n` or an empty/whitespace value — parsed during readTarEntriesFromBuffer.

Common situations: Archives written by non-conforming tools, hand-edited or corrupted PAX headers, or a writer that put a formatted (hex, suffixed) number into a PAX record.

Related errors


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