vercel-labs/skills · error · Error

Invalid zip archive: ${label} is out of bounds

Error message

Invalid zip archive: ${label} is out of bounds

What it means

This error is thrown by the zip parser's internal bounds checker, ensureRange, whenever a computed offset/length pair falls outside the archive buffer. It means the parser located a structure (central directory, extra field, zip64 record) whose declared position or size points past the end (or before the start) of the Buffer being parsed. It almost always indicates a truncated or corrupt zip file rather than a misuse of the API.

Source

Thrown at src/archive.ts:41

  maxEntries: number;
}

export class ArchiveValidationError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ArchiveValidationError';
  }
}

function ensureRange(buffer: Buffer, offset: number, length: number, label: string): void {
  if (
    !Number.isSafeInteger(offset) ||
    !Number.isSafeInteger(length) ||
    offset < 0 ||
    length < 0 ||
    offset + length > buffer.length
  ) {
    throw new Error(`Invalid zip archive: ${label} is out of bounds`);
  }
}

function findEndOfCentralDirectory(buffer: Buffer): number {
  const minOffset = Math.max(0, buffer.length - ZIP_MAX_COMMENT_SIZE - ZIP_END_MIN_SIZE);
  for (let offset = buffer.length - ZIP_END_MIN_SIZE; offset >= minOffset; offset--) {
    if (buffer.readUInt32LE(offset) !== ZIP_END_OF_CENTRAL_DIRECTORY) continue;

    const commentLength = buffer.readUInt16LE(offset + 20);
    if (offset + ZIP_END_MIN_SIZE + commentLength === buffer.length) {
      return offset;
    }
  }
  return -1;
}

function readUInt64AsNumber(buffer: Buffer, offset: number, label: string): number {
  ensureRange(buffer, offset, 8, label);

View on GitHub (pinned to 435076e789)

Solutions

  1. Verify the file transfer completed before parsing (compare Content-Length to bytes received, or re-download and retry).
  2. Check the file is a real zip: run `unzip -t file.zip` or check the magic bytes PK\x03\x04 before handing it to the library.
  3. Ensure you read the entire file into the Buffer (no partial fs.read / stream truncation) and that nothing mutated the buffer afterwards.
  4. If the input is user-supplied, validate its integrity (CRC/checksum or size against a manifest) before parsing.

Example fix

// before
const buffer = await fs.promises.readFile(partialPath);
const zip = readZipArchive(buffer); // may throw 'out of bounds'

// after
const buffer = await fs.promises.readFile(partialPath);
if (buffer.subarray(0, 2).toString('binary') !== 'PK') {
  throw new Error('Not a zip file');
}
if (bytesReceived !== expectedSize) {
  throw new Error('Incomplete download');
}
const zip = readZipArchive(buffer);
Defensive patterns

Strategy: validation

Validate before calling

function looksLikeCompleteZip(buffer: Buffer): boolean {
  return (
    buffer.length >= 22 &&
    buffer.subarray(0, 2).toString('binary') === 'PK' &&
    buffer.lastIndexOf(Buffer.from([0x50, 0x4b, 0x05, 0x06])) !== -1 // EOCD present
  );
}

Type guard

null

Try / catch

try {
  const zip = readZipArchive(buffer);
} catch (e) {
  if ((e as Error).message.includes('out of bounds')) {
    // treat as truncated/corrupt input: reject the file or re-fetch
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a truncated zip Buffer (e.g. an incomplete download or partial stream write) to readZipArchive; a central directory offset field that was corrupted and points beyond buffer.length; a zip64 record whose declared size (recordSize + 12) overruns the buffer; an extra field whose length extends past its record.

Common situations: Downloading a zip over an interrupted HTTP stream and parsing before completion; reading a file concurrently while it is still being written; a git-lfs or cloud-storage placeholder file that is smaller than the real artifact; hand-crafted or fuzzed zip test fixtures with bogus offsets.

Related errors


AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28). Data as JSON: /api/errors/c07a8010bec747aa. Report an issue: GitHub.