can1357/oh-my-pi · error · ArchiveError

Invalid LZH level-1 packed size

Error message

Invalid LZH level-1 packed size

What it means

Thrown for a level-1 LZH member when, after subtracting the total extended-header bytes (or taking the header-declared packed size), the remaining packed size is negative. The member's compressed payload cannot have negative length, so the header fields are inconsistent.

Source

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

				if (extensionSize < 3) throw new ArchiveError("Invalid LZH extended header size");
				assertRange(bytes, cursor, cursor + extensionSize, "extended header");
				totalExtensionSize += extensionSize;
				assertIndexSize(headerLength + 2 + totalExtensionSize, options.limits, "header metadata");
				if (++extensionCount > 65_535) throw new ArchiveError("Invalid LZH archive: too many extended headers");
				const type = bytes[cursor]!;
				const dataEnd = cursor + extensionSize - 2;
				const data = bytes.subarray(cursor + 1, dataEnd);
				if (type === 0x01 || type === 0x02 || type === 0x44 || type === 0x45) {
					assertArchivePathBytes(data.byteLength, "member path", options.limits.maxPathBytes);
				}
				processExtendedHeader(type, data, cursor + 1, fields);
				const currentSize = extensionSize;
				extensionSize = u16(bytes, dataEnd);
				cursor += currentSize;
			}
			dataStart = baseEnd + totalExtensionSize;
			packedSize = fields.packedSize ?? packedSize - totalExtensionSize;
			if (packedSize < 0) throw new ArchiveError("Invalid LZH level-1 packed size");
		}
	} else {
		const headerLength = u16(bytes, offset);
		if (headerLength < 26) throw new ArchiveError("Invalid LZH level-2 header size");
		const headerEnd = offset + headerLength;
		assertRange(bytes, offset, headerEnd, "header");
		crc = u16(bytes, offset + 21);
		osId = bytes[offset + 23]!;
		mtimeMs = u32(bytes, offset + 15) * 1000;
		let cursor = offset + 24;
		let extensionCount = 0;
		while (cursor + 2 <= headerEnd) {
			const extensionSize = u16(bytes, cursor);
			if (extensionSize === 0) {
				cursor += 2;
				break;
			}
			if (extensionSize < 3 || cursor + extensionSize > headerEnd)

View on GitHub (pinned to 9690622007)

Solutions

  1. Replace the archive with an intact copy
  2. Repack with a standard LHA tool
  3. If you write LZH files, ensure packedSize accounting includes/excludes extended headers per the level-1 spec

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

if (u32(bytes, 7) > bytes.byteLength) throw new Error('packed size exceeds file');

Try / catch

try { parse(); } catch (err) { if (err instanceof ArchiveError && err.message.includes('packed size')) reject(err); else throw err; }

Prevention

When it happens

Trigger: A level-1 header where the recorded packed size is smaller than the sum of its extended headers, or where the packedSize extension field itself is malformed.

Common situations: Corrupted or truncated archives, non-conforming writers that misaccount extension sizes, fuzzed inputs.

Related errors


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