can1357/oh-my-pi · error · ArchiveError
Invalid ZIP archive: local and central compression methods d
Error message
Invalid ZIP archive: local and central compression methods disagree for '${memberPath}' What it means
Thrown when the compression method recorded in the member's local file header (offset 8) differs from the method in its central directory entry. A well-formed ZIP must have identical methods in both headers; disagreement means the archive was corrupted or hand-modified, so the library refuses to decode with either guess. ArchiveError naming the member.
Source
Thrown at packages/utils/src/ar/zip.ts:413
if (SUPPORTED_METHODS[this.#method] !== true) {
throw new ArchiveError(`Unsupported ZIP compression method ${this.#method} for '${memberPath}'`);
}
const headerEnd = checkedEnd(
this.#localHeaderOffset,
30,
this.#source.size,
`local header for '${memberPath}'`,
);
const header = await this.#source.read(this.#localHeaderOffset, headerEnd);
if (header.byteLength !== 30 || readUInt32LE(header, 0) !== LOCAL_HEADER_SIGNATURE) {
throw new ArchiveError(`Invalid ZIP archive: malformed local header for '${memberPath}'`);
}
const localFlags = readUInt16LE(header, 6);
if ((localFlags & (ENCRYPTED_FLAG | STRONG_ENCRYPTION_FLAG)) !== 0) {
throw new ArchiveError(`Encrypted ZIP member '${memberPath}' is not supported`);
}
if (readUInt16LE(header, 8) !== this.#method) {
throw new ArchiveError(
`Invalid ZIP archive: local and central compression methods disagree for '${memberPath}'`,
);
}
const dataStart = this.#localHeaderOffset + 30 + readUInt16LE(header, 26) + readUInt16LE(header, 28);
const dataEnd = checkedEnd(dataStart, this.#compressedSize, this.#source.size, `data for '${memberPath}'`);
if (this.#method === 0 && this.#compressedSize !== size) {
throw new ArchiveError(
`Invalid ZIP archive: size mismatch for '${memberPath}' (expected ${size}, got ${this.#compressedSize})`,
);
}
const compressed = await this.#source.read(dataStart, dataEnd);
if (compressed.byteLength !== this.#compressedSize) {
throw new ArchiveError(`Invalid ZIP archive: truncated data for '${memberPath}'`);
}
const decoded = await decodeMember(compressed, this.#method, size, memberPath);
if (decoded.byteLength !== size) {
throw new ArchiveError(
`Invalid ZIP archive: size mismatch for '${memberPath}' (expected ${size}, got ${decoded.byteLength})`,View on GitHub (pinned to 9690622007)
Solutions
- Verify the archive (`unzip -t`); if it fails, the file is corrupt — re-obtain it
- Re-create the archive from the original source files rather than repairing
- If repairing is required, use `zip -FF` which keeps headers consistent
- If the archive comes from your own writer, fix the writer to emit matching local/central methods
Example fix
// before: reading a hex-edited zip
await readZipMember(zip, 'data.bin'); // throws 3713
// after: repair then read
// $ `zip -FF broken.zip --out fixed.zip`
await readZipMember(await readZip(Bun.file('fixed.zip')), 'data.bin'); Defensive patterns
Strategy: validation
Validate before calling
// Cross-check local vs central method before reading
if (localHeaderMethod(entry) !== entry.method) throw new Error('zip headers inconsistent — archive is corrupt'); Try / catch
try {
const data = await zip.read(member);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('methods disagree')) {
// attempt structural repair once: await $`zip -FF broken.zip --out fixed.zip`
} else throw err;
} Prevention
- Never hand-edit ZIP bytes; re-create archives instead
- Use reputable writers (Info-ZIP, 7-Zip, zip command) that keep headers in sync
- Integrity-check (`unzip -t`) any archive that crossed an untrusted channel
- If repairs are routine, fix the producing writer, not the consumer
When it happens
Trigger: ZipMemberSource read where central directory says method X but the local header at localHeaderOffset says method Y — typically after byte-level patching, corrupting writes, or maliciously crafted archives.
Common situations: Archives repaired by naive tools that rewrite one header but not the other; files edited in hex or by scripts patching sizes/methods; deliberately malformed zips (fuzzing/security research); media with bit-rot.
Related errors
- Invalid ZIP archive: malformed local header for '${memberPat
- Invalid ZIP archive: ${what} has an invalid range
- Invalid ZIP archive: missing end of central directory
- Invalid ZIP archive: missing ZIP64 end of central directory
- Unsupported ZIP compression method ${this.#method} for '${me
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/92102391b54aab7f.
Report an issue: GitHub.