paperclipai/paperclip · error · Error
Invalid zip archive: truncated file contents.
Error message
Invalid zip archive: truncated file contents.
What it means
Guard in readZipArchive's local-entry scan loop: a local file header was found, but the computed body end (30-byte header + name + extra + compressedSize) extends past the end of the uploaded bytes. The archive's file contents are truncated relative to its declared entry sizes, so the entry cannot be extracted safely.
Solutions
- Re-download the complete archive; file contents are truncated.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/shared/src/portability-zip.ts:254 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@120ae5428f (2026-08-18).
Data as JSON: /api/errors/00a06aac0b2c7113.
Report an issue: GitHub.
Appendix: source
Thrown at packages/shared/src/portability-zip.ts:254
if (offset + 30 > bytes.length) {
throw new Error("Invalid zip archive: truncated local file header.");
}
const generalPurposeFlag = readUint16(bytes, offset + 6);
const compressionMethod = readUint16(bytes, offset + 8);
const compressedSize = readUint32(bytes, offset + 18);
const fileNameLength = readUint16(bytes, offset + 26);
const extraFieldLength = readUint16(bytes, offset + 28);
if ((generalPurposeFlag & 0x0008) !== 0) {
throw new Error("Unsupported zip archive: data descriptors are not supported.");
}
const nameOffset = offset + 30;
const bodyOffset = nameOffset + fileNameLength + extraFieldLength;
const bodyEnd = bodyOffset + compressedSize;
if (bodyEnd > bytes.length) {
throw new Error("Invalid zip archive: truncated file contents.");
}
localHeaderCount += 1;
const rawArchivePath = textDecoder.decode(bytes.slice(nameOffset, nameOffset + fileNameLength));
const archivePath = normalizeArchivePath(rawArchivePath);
const isDirectoryEntry = /\/$/.test(rawArchivePath.replace(/\\/g, "/"));
if (archivePath && !isDirectoryEntry) {
const entryBytes = inflateZipEntry(compressionMethod, bytes.slice(bodyOffset, bodyEnd), maxEntryDecompressedBytes);
totalDecompressedBytes += entryBytes.length;
if (totalDecompressedBytes > maxTotalDecompressedBytes) {
throw new Error(
`Unsupported zip archive: decompressed contents exceed the ${maxTotalDecompressedBytes}-byte limit.`,
);
}
entries.push({
path: archivePath,
body: bytesToPortableFileEntry(archivePath, entryBytes),
});View on GitHub (pinned to 120ae5428f)