can1357/oh-my-pi · error · ArchiveError
Invalid LZH level-2 header size
Error message
Invalid LZH level-2 header size
What it means
Thrown when a level-2 LZH header's 16-bit declared length is smaller than the 26-byte minimum required for its fixed fields. The header cannot contain the mandatory level-2 layout (CRC, OS id, timestamps), so parsing aborts.
Source
Thrown at packages/utils/src/ar/lzh.ts:531
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)
throw new ArchiveError("Invalid LZH extended header size");
if (++extensionCount > 65_535) throw new ArchiveError("Invalid LZH archive: too many extended headers");
const type = bytes[cursor + 2]!;
const data = bytes.subarray(cursor + 3, cursor + extensionSize);View on GitHub (pinned to 9690622007)
Solutions
- Obtain an uncorrupted copy of the archive
- Repack with a conforming tool (e.g. lha -w2 or a level-2 capable packer)
- Catch ArchiveError and reject the input if processing untrusted files
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
const headerLength = bytes[0] | (bytes[1] << 8); if (headerLength < 26) throw new Error('level-2 header too small'); Try / catch
try { parse(); } catch (err) { if (err instanceof ArchiveError && err.message.includes('level-2')) reject(err); else throw err; } Prevention
- Validate the u16 header length before delegating to the reader
- Fail fast on truncated inputs
When it happens
Trigger: Reading a level-2 LHA archive with a corrupt or truncated header-length field, or a file misidentified as level-2 LZH.
Common situations: Damaged downloads, archives from buggy level-2 writers, fuzzed or hostile inputs.
Related errors
- Invalid LZH level-${level} header size
- Invalid LZH header checksum
- Invalid ARJ archive: missing main header
- Invalid ARJ main header
- Invalid ${label} Huffman table: oversubscribed codes
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/52794c98228cb900.
Report an issue: GitHub.