{"record":{"id":"00a06aac0b2c7113","repo":"paperclipai/paperclip","slug":"invalid-zip-archive-truncated-file-contents","errorCode":null,"errorMessage":"Invalid zip archive: truncated file contents.","messagePattern":"Invalid zip archive: truncated file contents\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/shared/src/portability-zip.ts","lineNumber":254,"sourceCode":"    if (offset + 30 > bytes.length) {\n      throw new Error(\"Invalid zip archive: truncated local file header.\");\n    }\n\n    const generalPurposeFlag = readUint16(bytes, offset + 6);\n    const compressionMethod = readUint16(bytes, offset + 8);\n    const compressedSize = readUint32(bytes, offset + 18);\n    const fileNameLength = readUint16(bytes, offset + 26);\n    const extraFieldLength = readUint16(bytes, offset + 28);\n\n    if ((generalPurposeFlag & 0x0008) !== 0) {\n      throw new Error(\"Unsupported zip archive: data descriptors are not supported.\");\n    }\n\n    const nameOffset = offset + 30;\n    const bodyOffset = nameOffset + fileNameLength + extraFieldLength;\n    const bodyEnd = bodyOffset + compressedSize;\n    if (bodyEnd > bytes.length) {\n      throw new Error(\"Invalid zip archive: truncated file contents.\");\n    }\n\n    localHeaderCount += 1;\n    const rawArchivePath = textDecoder.decode(bytes.slice(nameOffset, nameOffset + fileNameLength));\n    const archivePath = normalizeArchivePath(rawArchivePath);\n    const isDirectoryEntry = /\\/$/.test(rawArchivePath.replace(/\\\\/g, \"/\"));\n    if (archivePath && !isDirectoryEntry) {\n      const entryBytes = inflateZipEntry(compressionMethod, bytes.slice(bodyOffset, bodyEnd), maxEntryDecompressedBytes);\n      totalDecompressedBytes += entryBytes.length;\n      if (totalDecompressedBytes > maxTotalDecompressedBytes) {\n        throw new Error(\n          `Unsupported zip archive: decompressed contents exceed the ${maxTotalDecompressedBytes}-byte limit.`,\n        );\n      }\n      entries.push({\n        path: archivePath,\n        body: bytesToPortableFileEntry(archivePath, entryBytes),\n      });","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/paperclipai/paperclip/blob/120ae5428fa29bee300bcf806491cd4d965fbb7c/packages/shared/src/portability-zip.ts#L236-L272","documentation":"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.","triggerScenarios":"Thrown at packages/shared/src/portability-zip.ts:254 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Re-download the complete archive; file contents are truncated."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"120ae5428fa29bee300bcf806491cd4d965fbb7c","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}