can1357/oh-my-pi · error · ArchiveError
Invalid ZIP archive: truncated data for '${memberPath}'
Error message
Invalid ZIP archive: truncated data for '${memberPath}' What it means
Thrown when the bytes actually read for a member are fewer than the declared compressed size — the data region extends past the end of the source. This means the archive is truncated: the central directory claims more payload bytes than exist. ArchiveError naming the member.
Source
Thrown at packages/utils/src/ar/zip.ts:426
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})`,
);
}
const actualCrc = crc32(decoded);
if (actualCrc !== this.#crc) {
throw new ArchiveError(`Invalid ZIP archive: CRC mismatch for '${memberPath}'`);
}
return decoded;
} catch (error) {
throw archiveError(error, `Failed to read ZIP member '${memberPath}'`);
}
}
}
View on GitHub (pinned to 9690622007)
Solutions
- Re-download the archive and compare byte length against the server's Content-Length or a published checksum
- Check disk space / copy completion — the file on disk may be short
- For HTTP sources, ensure the full body was read before parsing (await the stream end)
- Use `unzip -t` to confirm which members are recoverable; extract those individually
Example fix
// before: parsing before body completes
const res = await fetch(url);
const zip = await readZip(Bun.file(await res.arrayBuffer())); // may throw 3715 if body short
// after: verify length
const buf = new Uint8Array(await res.arrayBuffer());
if (buf.byteLength !== Number(res.headers.get('content-length'))) throw new Error('truncated download');
const zip = await readZip(buf); Defensive patterns
Strategy: validation
Validate before calling
const bytes = new Uint8Array(await file.arrayBuffer());
if (bytes.byteLength < declaredZipSize) throw new Error('archive truncated — re-download before parsing'); Try / catch
try {
const data = await zip.read(member);
} catch (err) {
if (err instanceof ArchiveError && err.message.includes('truncated data')) {
throw new Error('download incomplete; refetch with length verification');
}
throw err;
} Prevention
- Always compare downloaded size to Content-Length or a checksum before parsing
- Fully consume HTTP bodies / streams before handing bytes to the reader
- Guard against copying files that are still being written (watch for stable size)
- Retry with resumable downloads for large archives
When it happens
Trigger: ZipMemberSource read where source.read(dataStart, dataEnd) returns short because localHeaderOffset + 30 + nameLen + extraLen + compressedSize exceeds source size — typical of cut-off downloads, partial uploads, or a source buffer smaller than the archive.
Common situations: HTTP downloads interrupted before completion; files copied while still being written; fetching a zip over a flaky network and not verifying Content-Length; trimmed logs/attachments containing embedded zips.
Related errors
- 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
- Invalid ZIP archive: malformed local header for '${memberPat
- Invalid ZIP archive: local and central compression methods d
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6f611a5c63b42efa.
Report an issue: GitHub.