can1357/oh-my-pi · error · ArchiveError
Invalid LZH header checksum
Error message
Invalid LZH header checksum
What it means
Thrown when the single-byte additive checksum stored at offset+1 of a level-0/1 LZH header does not equal the sum (mod 256) of the header bytes from offset+2 through the end of the base header. This detects corruption in the header itself before any data is touched.
Source
Thrown at packages/utils/src/ar/lzh.ts:484
if (!LHA_METHOD_PATTERN.test(method)) throw new ArchiveError(`Invalid LZH compression method '${method}'`);
let packedSize = u32(bytes, offset + 7);
let size = u32(bytes, offset + 11);
let crc = 0;
let legacyFilename: string | undefined;
let mtimeMs: number | undefined;
let osId = 0;
let dataStart: number;
const fields: LzhExtendedFields = {};
if (level < 2) {
const headerLength = bytes[offset]!;
const minimum = level === 0 ? 22 : 25;
if (headerLength < minimum) throw new ArchiveError(`Invalid LZH level-${level} header size`);
const baseEnd = offset + headerLength + 2;
assertRange(bytes, offset, baseEnd, "header");
let sum = 0;
for (let index = offset + 2; index < baseEnd; index++) sum = (sum + bytes[index]!) & 0xff;
if (sum !== bytes[offset + 1]) throw new ArchiveError("Invalid LZH header checksum");
const nameLength = bytes[offset + 21]!;
if (22 + nameLength + 2 > headerLength + 2) throw new ArchiveError("Invalid LZH filename length");
assertArchivePathBytes(nameLength, "member path", options.limits.maxPathBytes);
legacyFilename = decodeLegacy(bytes.subarray(offset + 22, offset + 22 + nameLength));
crc = u16(bytes, offset + 22 + nameLength);
mtimeMs = dosTimeToMs(u32(bytes, offset + 15));
if (level === 0) {
const extendedStart = offset + 24 + nameLength;
if (baseEnd - extendedStart >= 12) {
const extended = bytes.subarray(extendedStart, baseEnd);
if ((extended[0] === 0x55 || extended[0] === 0x4b) && extended[1] === 0) {
osId = extended[0]!;
fields.mtimeMs = u32(extended, 2) * 1000;
fields.mode = u16(extended, extended.byteLength - 6);
}
}
dataStart = baseEnd;
} else {View on GitHub (pinned to 9690622007)
Solutions
- Obtain an uncorrupted copy of the archive and compare checksums
- Recreate the archive with a standard LHA tool that computes the header sum
- If you generate LZH files yourself, fix the writer to recompute the checksum byte after any header edit
Example fix
// before: editing the filename bytes in the header directly headerBytes[30] = 0x2d; // corrupts sum // after: recompute the checksum after edits for (let i = 2; i < headerEnd; i++) sum = (sum + headerBytes[i]) & 0xff; headerBytes[1] = sum;
Defensive patterns
Strategy: validation
Validate before calling
let sum = 0; for (let i = 2; i < bytes[0] + 2; i++) sum = (sum + bytes[i]) & 0xff;
if (sum !== bytes[1]) throw new Error('header checksum mismatch pre-check'); Try / catch
try { parse(); } catch (err) { if (err instanceof ArchiveError && err.message.includes('checksum')) reject(err); else throw err; } Prevention
- Recompute header sums when regenerating archives
- Store archives with fixity checksums
When it happens
Trigger: Reading an archive whose header bytes were modified or corrupted after creation (the checksum covers method, sizes, dates, filename).
Common situations: Files damaged by download/storage, archives edited by hand or by buggy tools that forgot to recompute the header checksum byte.
Related errors
- Invalid LZH level-${level} header size
- Invalid LZH level-2 header size
- Invalid ARJ archive: missing main header
- Invalid ARJ main header
- Invalid CAB archive: CFDATA block ${block} checksum mismatch
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/2df6f5aa22f50261.
Report an issue: GitHub.