can1357/oh-my-pi · error · ArchiveError

Archive member '${memberPath}' is truncated

Error message

Archive member '${memberPath}' is truncated

What it means

A member reader was asked for `size` bytes at the member's offset, but the underlying source returned fewer bytes — the archive data ends early. The library surfaces this as an ArchiveError naming the member rather than returning a short buffer.

Source

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

	size: number;
	mtimeSeconds?: number;
	mode?: number;
}

class ArMemberSource implements MemberSource {
	readonly #source: ByteSource;
	readonly #offset: number;

	constructor(source: ByteSource, offset: number) {
		this.#source = source;
		this.#offset = offset;
	}

	async read(size: number, memberPath: string): Promise<Uint8Array> {
		try {
			const bytes = await this.#source.read(this.#offset, this.#offset + size);
			if (bytes.byteLength !== size) {
				throw new ArchiveError(`Archive member '${memberPath}' is truncated`);
			}
			return bytes;
		} catch (error) {
			if (error instanceof ArchiveError) throw error;
			throw new ArchiveError(error instanceof Error ? error.message : String(error));
		}
	}
}

function decodeAsciiField(bytes: Uint8Array, offset: number, length: number): string {
	let end = offset + length;
	while (end > offset && bytes[end - 1] === 0x20) end--;
	let value = "";
	for (let index = offset; index < end; index++) {
		const byte = bytes[index]!;
		if (byte < 0x20 || byte > 0x7e) throw new ArchiveError("Invalid ar archive header field");
		value += String.fromCharCode(byte);
	}

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-obtain the archive from a complete, verified source (checksum) and retry
  2. Validate that the file length covers the header-declared member sizes before reading
  3. Fix the writer that emitted the incorrect size field

Example fix

// before
const data = await ar.read(header.size, header.name);
// after
if (this.#sourceLength - memberOffset < header.size) {
	throw new Error(`Archive truncated: member ${header.name}`);
}
const data = await ar.read(header.size, header.name);
Defensive patterns

Strategy: validation

Validate before calling

if (archiveByteLength - memberOffset < header.size) {
	throw new Error(`Truncated archive: '${header.name}' needs ${header.size} bytes`);
}

Try / catch

try {
	const data = await reader.read(header.size, header.name);
} catch (err) {
	if (err instanceof ArchiveError && err.message.includes("is truncated")) {
		// re-fetch the archive and verify its checksum
	}
	throw err;
}

Prevention

When it happens

Trigger: ArReader.read()/readAllBytes called on a truncated .ar file: the header claims a size larger than the bytes actually present in the file/stream.

Common situations: Interrupted download or upload of the archive; a hand-written ar file with a wrong/oversized size field; reading while the file is still being written.

Related errors


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