can1357/oh-my-pi · error · ArchiveError
Invalid LZH archive: no members
Error message
Invalid LZH archive: no members
What it means
readLzh parsed the byte buffer but found no member headers at all: the loop over header offsets never executed (first byte was 0 or the buffer ended immediately) after the initial LZH header sniff passed. The library throws because an LZH archive with zero members is not a usable container. This indicates the input is not really an LZH archive or is a degenerate/empty file that merely sniffs as LZH.
Source
Thrown at packages/utils/src/ar/lzh.ts:657
storage: { type: "link", targetPath, resolveTarget: false },
});
continue;
}
entries.push({
path: header.path,
isDirectory,
size: isDirectory ? 0 : header.size,
mtimeMs: header.mtimeMs,
mode: header.mode,
storage: isDirectory
? undefined
: {
type: "member",
source: new LzhMemberSource(bytes, header.dataStart, header.packedSize, header.method, header.crc),
},
});
}
if (entries.length === 0 && parsedCount === 0) throw new ArchiveError("Invalid LZH archive: no members");
return entries;
};
View on GitHub (pinned to 9690622007)
Solutions
- Verify the file is a genuine LZH archive (magic/method bytes like '-lh0-') with an external tool or hex inspection; re-download or re-export it if not.
- Check the caller supplied the intended path/bytes, not an empty or partially-written file.
- Confirm the file size is non-trivial; a 0/1-byte file cannot contain members.
- Catch ArchiveError and surface a clear 'not a valid archive' message to the user instead of retrying.
Example fix
// before
const entries = await openArchive(inputPath);
// after
if ((await Bun.file(inputPath).size) < 32) throw new Error(`${inputPath} is not a valid LZH archive (too small)`);
const entries = await openArchive(inputPath); Defensive patterns
Strategy: try-catch
Validate before calling
import { sniffLzh } from "@oh-my-pi/pi-utils/ar/lzh"; // or check first bytes manually
const bytes = new Uint8Array(await Bun.file(p).arrayBuffer());
if (bytes.length < 32 || !sniffLzh(bytes)) throw new Error(`${p} is not a valid LZH archive`); Try / catch
try {
const reader = await openArchive(p);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes("no members")) {
throw new Error(`${p} is empty or not a real LZH archive`);
}
throw err;
} Prevention
- Verify file size (>header+member minimum) before opening.
- Pre-check the archive with a sniff/inspect call before extraction.
- Treat zero-member archives from downloads as transfer failures and re-fetch.
- Log the input path and size when surfacing ArchiveError to users.
When it happens
Trigger: Calling the archive open/browse API on a path or bytes whose format was detected as LZH (readLzh via the format registry) but whose content begins with a 0x00 byte or has no parseable member headers, so entries.length === 0 && parsedCount === 0 at lzh.ts:657.
Common situations: Renamed or truncated downloads (a corrupt/empty file with an .lzh extension), placeholder files created by failed transfers, or misrouted format detection that sniffed a wrong-format blob as LZH.
Related errors
- Invalid XZ stream: padding without a stream
- Invalid XZ stream: footer magic mismatch
- Invalid XZ stream: footer CRC32 mismatch
- Invalid XZ stream: backward index size is invalid
- Invalid XZ stream: header position or magic is invalid
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ad81e46aedd56c91.
Report an issue: GitHub.