can1357/oh-my-pi · error · ArchiveError

Invalid ar archive: truncated member data

Error message

Invalid ar archive: truncated member data

What it means

After parsing a member header, header.physicalSize implied a payload end beyond the available bytes (or a non-safe integer). The member's data region is cut off, so the record cannot be represented and the archive is rejected.

Source

Thrown at packages/utils/src/ar/unix-ar.ts:209

	if (!sniffUnixAr(bytes)) throw new ArchiveError("Invalid ar archive signature");
}

/** Parse a fully materialized Unix ar archive for composition by formats such as deb. */
export function readUnixArEntriesFromBuffer(bytes: Uint8Array, options: FormatReadOptions): ArchiveIndexEntry[] {
	readSignatureFromBuffer(bytes);
	const records: RawArMember[] = [];
	let longNames: Uint8Array | undefined;
	let metadataSize = 0;
	for (let position = SIGNATURE.length; position < bytes.byteLength; ) {
		if (bytes.byteLength - position < HEADER_SIZE)
			throw new ArchiveError("Invalid ar archive: truncated member header");
		const header = parseHeader(readMemoryRange(bytes, position, position + HEADER_SIZE));
		metadataSize += HEADER_SIZE;
		assertIndexSize(metadataSize, options.limits, "index");
		const payloadOffset = position + HEADER_SIZE;
		const payloadEnd = payloadOffset + header.physicalSize;
		if (!Number.isSafeInteger(payloadEnd) || payloadEnd > bytes.byteLength) {
			throw new ArchiveError("Invalid ar archive: truncated member data");
		}
		let name = header.rawName;
		let nameByteLength = Buffer.byteLength(name, "utf-8");
		let dataOffset = payloadOffset;
		let size = header.physicalSize;
		if (header.bsdNameLength !== undefined) {
			metadataSize += header.bsdNameLength;
			assertIndexSize(metadataSize, options.limits, "index");
			const nameBytes = readMemoryRange(bytes, payloadOffset, payloadOffset + header.bsdNameLength);
			const decoded = decodeBsdName(nameBytes, options.limits);
			name = decoded.name;
			nameByteLength = decoded.byteLength;
			dataOffset += header.bsdNameLength;
			size -= header.bsdNameLength;
		} else if (header.rawName === "//") {
			metadataSize += header.physicalSize;
			assertIndexSize(metadataSize, options.limits, "index");
			longNames = readMemoryRange(bytes, payloadOffset, payloadEnd);

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-download/rebuild the archive and verify checksums; the data is genuinely cut off.
  2. Check the size field of the last header with a hex editor if you must salvage; fix or extract with GNU ar.
  3. Ensure the producing tool wrote the correct padded size (BSD ar pads extended names to even lengths).
  4. Pre-compute expected archive size from members when generating, and compare before parsing.

Example fix

// before: trusting header size blindly when salvaging
const entries = await readUnixAr(untrustedBytes);
// after: verify size field plausibility first
const size = view.getBigUint64(offset, true); // inspect header size
if (size > BigInt(untrustedBytes.byteLength)) throw new Error('oversized member size');
Defensive patterns

Strategy: validation

Validate before calling

// plausible sanity: last 60-byte header's size must fit within the file
const lastHeader = bytes.byteLength - 60;
if (lastHeader >= 8) {
  const sizeText = new TextDecoder().decode(bytes.subarray(lastHeader + 48, lastHeader + 58)).trim();
  const size = Number(sizeText);
  if (Number.isFinite(size) && 8 + lastHeader + 60 + size > bytes.byteLength) {
    throw new Error('archive truncated: final member data incomplete');
  }
}

Try / catch

try {
  return await readUnixAr(source);
} catch (err) {
  if (err instanceof ArchiveError && err.message.includes('truncated member data')) {
    throw new Error(`archive member data cut off — file incomplete or corrupt`);
  }
  throw err;
}

Prevention

When it happens

Trigger: A member header's size field claims more data than exists (truncated archive, or a corrupted/huge size field like 0xFFFFFFFFFFFFFFFF that breaks Number.isSafeInteger after offset addition).

Common situations: Interrupted downloads; archives written with a wrong size field by a buggy tool; corrupted size bytes; mixing ar variants where BSD extended names shift offsets.

Related errors


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