can1357/oh-my-pi · error · ArchiveError
LZH uses the incompatible LHARK -lh7- variant
Error message
LZH uses the incompatible LHARK -lh7- variant
What it means
LHARK is an unofficial LZH variant that reuses the -lh7- method with level-1 headers and OS id 0x20 (MS-DOS) but changes the compression algorithm's tables. It is not decodable by this library, so it is detected and rejected up front instead of producing garbage output.
Source
Thrown at packages/utils/src/ar/lzh.ts:561
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);
if (type === 0x01 || type === 0x02 || type === 0x44 || type === 0x45) {
assertArchivePathBytes(data.byteLength, "member path", options.limits.maxPathBytes);
}
processExtendedHeader(type, data, cursor + 3, fields);
cursor += extensionSize;
}
if (cursor !== headerEnd) throw new ArchiveError("Invalid LZH level-2 extended header chain");
dataStart = headerEnd;
packedSize = fields.packedSize ?? packedSize;
}
if (level === 1 && osId === 0x20 && method === "-lh7-") {
throw new ArchiveError("LZH uses the incompatible LHARK -lh7- variant");
}
size = fields.size ?? size;
mtimeMs = fields.mtimeMs ?? mtimeMs;
const mode = fields.mode;
if (fields.commonCrc !== undefined) {
const relative = fields.commonCrcOffset! - offset;
if (crc16WithZeroRange(bytes.subarray(offset, dataStart), relative, relative + 2) !== fields.commonCrc) {
throw new ArchiveError("Invalid LZH common header CRC-16");
}
}
const filename = fields.unicodeFilename ?? fields.filename ?? legacyFilename ?? "";
const directory = fields.unicodeDirectory ?? fields.directory ?? "";
const rawPath = `${directory}${directory && !/[\\/]$/.test(directory) ? "/" : ""}${filename}`;
assertArchivePathString(rawPath, "member path", options.limits.maxPathBytes);
assertArchiveMemberSize(size, rawPath || "<unnamed>", options.limits);
assertRange(bytes, dataStart, dataStart + packedSize, "member data");
return {View on GitHub (pinned to 9690622007)
Solutions
- Identify the file as LHARK-created; use a tool that supports LHARK (e.g. the original LHARK under DOS emulation) to extract it.
- Re-compress the contents with a standard LHA tool (-lh5-/-lh6-/-lh7- from LHA/lhasa) and use the new archive.
- If you only need the contents, extract externally and feed individual files to your pipeline instead.
- Catch ArchiveError with this message and surface a clear 'LHARK variant unsupported' notice to end users.
Example fix
// before
const entries = await readLzh(source, options);
// after
try {
const entries = await readLzh(source, options);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("LHARK")) {
throw new Error("This is a LHARK archive; convert it with a standard LHA tool first");
}
throw err;
} Defensive patterns
Strategy: fallback
Validate before calling
// detect the LHARK signature before reading
const bytes = await readAllBytes(source);
const method = String.fromCharCode(bytes[2], bytes[3], bytes[4], bytes[5], bytes[6]);
if (method === "-lh7-" && bytes[20] === 1) {
throw new Error("LHARK variant detected — convert with an LHARK-aware tool first");
} Try / catch
try {
const entries = await readLzh(source, options);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("LHARK")) {
return extractLharkExternally(path); // fallback path
}
throw err;
} Prevention
- Screen archives for the LHARK signature (-lh7- level-1) in ingest pipelines
- Convert LHARK archives to standard LHA during ingestion
- Document that only standard LZH levels 0-2 methods are supported
When it happens
Trigger: readLzh() on a level-1 header with osId 0x20 and compression method -lh7-.
Common situations: Archives created by the LHARK archiver (rare, mostly from Japanese/DOS-era sources) mislabeled as standard LHA; users confusing LHARK files with regular .lzh files.
Related errors
- Unsupported archive format: ${assetName}
- Unsupported ISO 9660 logical block size ${blockSize} (expect
- Invalid ${label} Huffman table: oversubscribed codes
- Invalid ${label} Huffman table: incomplete codes
- Invalid ${label} Huffman table: prefix collision
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/11817d1cf46ae51a.
Report an issue: GitHub.