{"record":{"id":"4355127f5d33262b","repo":"vercel-labs/skills","slug":"zip-entry-size-mismatch","errorCode":null,"errorMessage":"Zip entry size mismatch","messagePattern":"Zip entry size mismatch","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/archive.ts","lineNumber":388,"sourceCode":"    ensureRange(buffer, dataOffset, compressedSize, 'file data');\n    if (dataOffset + compressedSize > centralDirectory.offset) {\n      throw new Error('Invalid zip archive: file data overlaps central directory');\n    }\n\n    const compressed = buffer.subarray(dataOffset, dataOffset + compressedSize);\n    let contents: Buffer;\n    if (method === 0) {\n      contents = compressed;\n    } else if (method === 8) {\n      contents = inflateRawSync(compressed, {\n        maxOutputLength: uncompressedSize + 1,\n      });\n    } else {\n      throw new Error(`Unsupported zip compression method: ${method}`);\n    }\n\n    if (contents.byteLength !== uncompressedSize) {\n      throw new Error('Zip entry size mismatch');\n    }\n    if (crc32(contents) !== expectedChecksum) {\n      throw new Error('Zip entry checksum mismatch');\n    }\n    files.set(fileName, new Uint8Array(contents));\n  }\n\n  if (offset !== centralDirectory.offset + centralDirectory.size) {\n    throw new Error('Invalid zip central directory size');\n  }\n\n  return files;\n}\n","sourceCodeStart":370,"sourceCodeEnd":402,"githubUrl":"https://github.com/vercel-labs/skills/blob/435076e78988e1e6ec40d00b0b1d76bdbbc5419a/src/archive.ts#L370-L402","documentation":"Thrown by readZipArchive after inflating a zip entry when the decompressed byteLength does not match the uncompressedSize declared in the entry's local/central directory header. It is a structural integrity check: the archive metadata promises N bytes but the decompressor produced a different count. This usually indicates a truncated or corrupted download, or a zip written with unusual/unsupported fields.","triggerScenarios":"Calling extractArchive (or readZipArchive directly) on a .zip whose entry header declares an uncompressedSize that differs from the actual inflated output — typically after a partial/interrupted download, a proxy mangling the body, or a hand-crafted/nonstandard zip.","commonSituations":"Interrupted downloads (partial file saved), corrupted artifacts from CI caches, zips produced by exotic archivers that the minimal reader misparses, or bit-rot in cached tarballs.","solutions":["Re-download the archive and verify its SHA/size against the source before extracting","Test the file with an independent tool (unzip -t file.zip) to confirm corruption","If the zip legitimately uses features the reader mishandles (e.g. data descriptors, zip64), extract it externally and point the tool at the extracted directory or a local path instead","Report a bug if unzip -t passes but this library still fails"],"exampleFix":"# before\nskills add https://example.com/skills.zip  # fails: Zip entry size mismatch\n\n# after\ncurl -L -o skills.zip https://example.com/skills.zip\nunzip -t skills.zip            # verify integrity\nskills add ./skills.zip","handlingStrategy":"validation","validationCode":"// Pre-validate the archive with an independent tool before extracting\nimport { execFileSync } from 'node:child_process';\nfunction assertZipIntegrity(path: string): void {\n  execFileSync('unzip', ['-t', path], { stdio: 'pipe' }); // throws on corrupt zip\n}","typeGuard":"null","tryCatchPattern":"try {\n  await extractArchive(file);\n} catch (err) {\n  if (err instanceof Error && err.message === 'Zip entry size mismatch') {\n    // treat as corrupt download: delete artifact and re-fetch from source\n  } else throw err;\n}","preventionTips":["Verify downloaded archive hashes against published checksums","Always extract to a fresh temp directory so retries start clean"],"tags":["zip","archive","integrity","corruption"],"backgroundTag":"archive-corruption-detected","analyzedSha":"435076e78988e1e6ec40d00b0b1d76bdbbc5419a","analyzedAt":"2026-08-28T17:47:53.369Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}