{"record":{"id":"2df6f5aa22f50261","repo":"can1357/oh-my-pi","slug":"invalid-lzh-header-checksum","errorCode":null,"errorMessage":"Invalid LZH header checksum","messagePattern":"Invalid LZH header checksum","errorType":"validation","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/lzh.ts","lineNumber":484,"sourceCode":"\tif (!LHA_METHOD_PATTERN.test(method)) throw new ArchiveError(`Invalid LZH compression method '${method}'`);\n\tlet packedSize = u32(bytes, offset + 7);\n\tlet size = u32(bytes, offset + 11);\n\tlet crc = 0;\n\tlet legacyFilename: string | undefined;\n\tlet mtimeMs: number | undefined;\n\tlet osId = 0;\n\tlet dataStart: number;\n\tconst fields: LzhExtendedFields = {};\n\n\tif (level < 2) {\n\t\tconst headerLength = bytes[offset]!;\n\t\tconst minimum = level === 0 ? 22 : 25;\n\t\tif (headerLength < minimum) throw new ArchiveError(`Invalid LZH level-${level} header size`);\n\t\tconst baseEnd = offset + headerLength + 2;\n\t\tassertRange(bytes, offset, baseEnd, \"header\");\n\t\tlet sum = 0;\n\t\tfor (let index = offset + 2; index < baseEnd; index++) sum = (sum + bytes[index]!) & 0xff;\n\t\tif (sum !== bytes[offset + 1]) throw new ArchiveError(\"Invalid LZH header checksum\");\n\t\tconst nameLength = bytes[offset + 21]!;\n\t\tif (22 + nameLength + 2 > headerLength + 2) throw new ArchiveError(\"Invalid LZH filename length\");\n\t\tassertArchivePathBytes(nameLength, \"member path\", options.limits.maxPathBytes);\n\t\tlegacyFilename = decodeLegacy(bytes.subarray(offset + 22, offset + 22 + nameLength));\n\t\tcrc = u16(bytes, offset + 22 + nameLength);\n\t\tmtimeMs = dosTimeToMs(u32(bytes, offset + 15));\n\t\tif (level === 0) {\n\t\t\tconst extendedStart = offset + 24 + nameLength;\n\t\t\tif (baseEnd - extendedStart >= 12) {\n\t\t\t\tconst extended = bytes.subarray(extendedStart, baseEnd);\n\t\t\t\tif ((extended[0] === 0x55 || extended[0] === 0x4b) && extended[1] === 0) {\n\t\t\t\t\tosId = extended[0]!;\n\t\t\t\t\tfields.mtimeMs = u32(extended, 2) * 1000;\n\t\t\t\t\tfields.mode = u16(extended, extended.byteLength - 6);\n\t\t\t\t}\n\t\t\t}\n\t\t\tdataStart = baseEnd;\n\t\t} else {","sourceCodeStart":466,"sourceCodeEnd":502,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/lzh.ts#L466-L502","documentation":"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.","triggerScenarios":"Reading an archive whose header bytes were modified or corrupted after creation (the checksum covers method, sizes, dates, filename).","commonSituations":"Files damaged by download/storage, archives edited by hand or by buggy tools that forgot to recompute the header checksum byte.","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"],"exampleFix":"// before: editing the filename bytes in the header directly\nheaderBytes[30] = 0x2d; // corrupts sum\n// after: recompute the checksum after edits\nfor (let i = 2; i < headerEnd; i++) sum = (sum + headerBytes[i]) & 0xff;\nheaderBytes[1] = sum;","handlingStrategy":"validation","validationCode":"let sum = 0; for (let i = 2; i < bytes[0] + 2; i++) sum = (sum + bytes[i]) & 0xff;\nif (sum !== bytes[1]) throw new Error('header checksum mismatch pre-check');","typeGuard":null,"tryCatchPattern":"try { parse(); } catch (err) { if (err instanceof ArchiveError && err.message.includes('checksum')) reject(err); else throw err; }","preventionTips":["Recompute header sums when regenerating archives","Store archives with fixity checksums"],"tags":["archive","lzh","header","checksum","corruption"],"backgroundTag":"corrupt-archive-header","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}