paperclipai/paperclip · error · Error

Invalid zip archive: missing end-of-central-directory record

Error message

Invalid zip archive: missing end-of-central-directory record.

What it means

Signature-scan failure in readZipArchive's EOCD lookup (findEndOfCentralDirectoryOffset returned -1): no end-of-central-directory record exists anywhere in the bytes. Without the EOCD there is no authoritative entry count, so the buffer is not a complete zip archive and is rejected before central-directory validation.

Source

Thrown at packages/shared/src/portability-zip.ts:289

        body: bytesToPortableFileEntry(archivePath, entryBytes),
      });
    }

    offset = bodyEnd;
  }

  // A complete archive always ends with a central directory after its local
  // entries. If the scan ran off the end of the buffer without reaching one, the
  // upload was truncated at a record boundary — fail closed rather than import a
  // leading fragment. Then fully validate the central directory the EOCD points
  // at so a truncated tail with a forged EOCD (whose count happens to match the
  // surviving entries) cannot smuggle in a partial import.
  if (!reachedCentralDirectory) {
    throw new Error("Invalid zip archive: truncated before the central directory.");
  }
  const eocdOffset = findEndOfCentralDirectoryOffset(bytes);
  if (eocdOffset === -1) {
    throw new Error("Invalid zip archive: missing end-of-central-directory record.");
  }
  validateCentralDirectory(bytes, eocdOffset, localHeaderCount);

  const rootPath = sharedArchiveRoot(entries.map((entry) => entry.path));
  const files: Record<string, CompanyPortabilityFileEntry> = {};
  for (const entry of entries) {
    const normalizedPath =
      rootPath && entry.path.startsWith(`${rootPath}/`)
        ? entry.path.slice(rootPath.length + 1)
        : entry.path;
    if (!normalizedPath) continue;
    // Two entries that normalize to the same path (e.g. `a/b` and `a//b`) make
    // the package ambiguous; reject it rather than silently letting the later
    // entry's contents win over the earlier one.
    if (Object.prototype.hasOwnProperty.call(files, normalizedPath)) {
      throw new Error(`Invalid zip archive: duplicate entry path "${normalizedPath}".`);
    }
    files[normalizedPath] = entry.body;

View on GitHub (pinned to 120ae5428f)

Solutions

  1. Re-create/re-download the archive; the end-of-central-directory record is missing.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/shared/src/portability-zip.ts:289 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/5850b5fa975b780d. Report an issue: GitHub.