{"record":{"id":"954d886915102c6b","repo":"can1357/oh-my-pi","slug":"unsupported-lzh-header-level-level","errorCode":null,"errorMessage":"Unsupported LZH header level ${level}","messagePattern":"Unsupported LZH header level (.+?)","errorType":"exception","errorClass":"ArchiveError","httpStatus":null,"severity":"error","filePath":"packages/utils/src/ar/lzh.ts","lineNumber":464,"sourceCode":"\t}\n}\n\ninterface ParsedLzhHeader {\n\tmethod: string;\n\tpackedSize: number;\n\tsize: number;\n\tdataStart: number;\n\tnextOffset: number;\n\tcrc: number;\n\tpath?: string;\n\tmtimeMs?: number;\n\tmode?: number;\n}\n\nfunction parseLzhHeader(bytes: Uint8Array, offset: number, options: FormatReadOptions): ParsedLzhHeader {\n\tassertRange(bytes, offset, offset + 22, \"header\");\n\tconst level = bytes[offset + 20]!;\n\tif (level > 2) throw new ArchiveError(`Unsupported LZH header level ${level}`);\n\tconst method = String.fromCharCode(...bytes.subarray(offset + 2, offset + 7));\n\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;","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/ar/lzh.ts#L446-L482","documentation":"Thrown when parsing an LZH header whose level byte (offset+20) is greater than 2. This library supports LHA header levels 0, 1, and 2 only; level 3 headers use a different structure entirely. The library refuses to guess at unknown formats rather than misparse bytes.","triggerScenarios":"Reading an LHA file that uses level-3 headers (rare, produced by some UnLHA variants), or pointing the reader at a non-LZH file whose bytes coincidentally pass initial framing (e.g. magic check) but have a garbage level byte.","commonSituations":"Processing obscure archives generated by Japanese LHA tools using level-3 format, or accidentally passing a corrupted/mislabeled file (e.g. a ZIP renamed .lzh) to the LZH reader.","solutions":["Convert the archive to a level-0/1/2 LHA file using lha or 7-Zip before reading","Use a different extraction tool/library that supports LZH level-3 headers","Verify the file is actually an LZH archive (check the -lh?- magic at offset 2)"],"exampleFix":"// before: feeding the raw file to the LZH reader\nconst archive = lzhRead(suspiciousBytes);\n// after: probe the method signature first\nconst method = String.fromCharCode(...bytes.subarray(2, 7));\nif (!/^-(lz|lh)[0-9a-z]-$/i.test(method)) throw new Error('not an LZH file');\nconst archive = lzhRead(bytes);","handlingStrategy":"fallback","validationCode":"if (!looksLikeLzh(bytes)) routeToOtherReader(bytes);","typeGuard":"function looksLikeLzh(b: Uint8Array): boolean { return /^-(lh|lz)[0-9a-z]-$/.test(String.fromCharCode(...b.subarray(2,7))); }","tryCatchPattern":"try { return lzhRead(bytes); } catch (err) { if (err instanceof ArchiveError) return fallbackExtractor(bytes); throw err; }","preventionTips":["Route files by signature, not extension","Convert legacy formats before ingestion"],"tags":["archive","lzh","format","unsupported"],"backgroundTag":"unsupported-archive-format","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}