can1357/oh-my-pi · error · ArchiveError

LZH member '${memberPath}' has inconsistent stored size

Error message

LZH member '${memberPath}' has inconsistent stored size

What it means

For stored (uncompressed) methods -lh0- and -lz4-, the packed data length must exactly equal the declared uncompressed size, since there is no compression to transform it. A mismatch means the header sizes or the data extent are wrong, so the reader throws.

Source

Thrown at packages/utils/src/ar/lzh.ts:418

	readonly #method: string;
	readonly #crc: number;

	constructor(archive: Uint8Array, start: number, packedSize: number, method: string, crc: number) {
		this.#archive = archive;
		this.#start = start;
		this.#packedSize = packedSize;
		this.#method = method;
		this.#crc = crc;
	}

	async read(size: number, memberPath: string): Promise<Uint8Array> {
		const packed = this.#archive.subarray(this.#start, this.#start + this.#packedSize);
		let output: Uint8Array;
		switch (this.#method) {
			case "-lh0-":
			case "-lz4-":
				if (packed.byteLength !== size)
					throw new ArchiveError(`LZH member '${memberPath}' has inconsistent stored size`);
				output = packed.slice();
				break;
			case "-lh4-":
				output = decompressLhStatic(packed, size, 1 << 12, 4, 13, "LZH -lh4-");
				break;
			case "-lh5-":
				output = decompressLhStatic(packed, size, 1 << 13, 4, 14, "LZH -lh5-");
				break;
			case "-lh6-":
				output = decompressLhStatic(packed, size, 1 << 15, 5, 16, "LZH -lh6-");
				break;
			case "-lh7-":
				output = decompressLhStatic(packed, size, 1 << 16, 5, 17, "LZH -lh7-");
				break;
			case "-lzs-":
				output = decompressLzs(packed, size);
				break;
			case "-lh1-":

View on GitHub (pinned to 9690622007)

Solutions

  1. Re-obtain the archive; for stored members the sizes must match and a mismatch proves corruption
  2. Check whether the file was truncated (compare to expected size/checksum) and re-download
  3. Repack the archive with a standard tool (7-Zip, lha) to regenerate consistent headers
  4. If you write LZH archives, set packedSize === size for -lh0-/-lz4- members

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

// For stored members, packed size must equal declared size
function storedSizeConsistent(packedSize: number, size: number, method: string): boolean {
	return !(method === "-lh0-" || method === "-lz4-") || packedSize === size;
}

Type guard

function isStoredMethod(method: string): method is "-lh0-" | "-lz4-" {
	return method === "-lh0-" || method === "-lz4-";
}

Try / catch

try {
	const data = await member.read();
} catch (err) {
	if (err instanceof ArchiveError && err.message.includes("inconsistent stored size")) {
		// header/data corruption — re-download or repack
	}
	throw err;
}

Prevention

When it happens

Trigger: Calling member read/extract on an LZH entry whose method is -lh0- or -lz4- but whose stored packedSize differs from the declared uncompressed size — typically after header corruption, a bad 0x42 64-bit-size override, or truncation of the archive buffer.

Common situations: Corrupted or truncated stored archives; archives where extended headers misreport sizes; self-written LZH tooling that writes inconsistent size fields.

Related errors


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