nexu-io/open-design · error · Error
invalid zip central directory entry
Error message
invalid zip central directory entry
What it means
Thrown by readCentralDirectory while walking the declared number of central-directory entries. Each entry must begin with the central-directory file-header signature 0x02014b50 (CENTRAL_SIG). If the 4 bytes at the current offset don't match, the central directory is corrupt, truncated, or the walking offset has desynchronized because a prior entry's nameLen/extraLen/commentLen fields were wrong. The HTTP route POST /api/import/claude-design maps this to 400.
Source
Thrown at apps/daemon/src/design/claude-design-import.ts:196
};
const onGestureEnd = (e) => { e.preventDefault(); e.stopPropagation(); isGesturing = false; };`);
return { result, wheelMatched, gestureMatched };
}
function readCentralDirectory(zip: Buffer): ZipEntry[] {
const eocdOffset = findEndOfCentralDirectory(zip);
const entryCount = zip.readUInt16LE(eocdOffset + 10);
const centralSize = zip.readUInt32LE(eocdOffset + 12);
const centralOffset = zip.readUInt32LE(eocdOffset + 16);
if (centralOffset + centralSize > zip.length) {
throw new Error('invalid zip central directory');
}
const entries: ZipEntry[] = [];
let offset = centralOffset;
for (let i = 0; i < entryCount; i += 1) {
if (zip.readUInt32LE(offset) !== CENTRAL_SIG) {
throw new Error('invalid zip central directory entry');
}
const flags = zip.readUInt16LE(offset + 8);
const method = zip.readUInt16LE(offset + 10);
const compressedSize = zip.readUInt32LE(offset + 20);
const uncompressedSize = zip.readUInt32LE(offset + 24);
const nameLen = zip.readUInt16LE(offset + 28);
const extraLen = zip.readUInt16LE(offset + 30);
const commentLen = zip.readUInt16LE(offset + 32);
const localOffset = zip.readUInt32LE(offset + 42);
const name = zip.slice(offset + 46, offset + 46 + nameLen).toString('utf8');
if ((flags & 1) !== 0) throw new Error('encrypted zip entries are not supported');
if (method !== 0 && method !== 8) {
throw new Error(`unsupported zip compression method: ${method}`);
}
entries.push({
name,
method,
compressedSize,View on GitHub (pinned to 5be4028344)
Solutions
- Re-export the Claude Design project to a fresh zip and retry the upload.
- Verify the archive opens in a standard unzip tool (e.g. `unzip -t file.zip`) before uploading.
- Confirm the multipart upload completed fully (compare uploaded size to source size).
- If the zip is generated programmatically, validate central-directory consistency with a conformant zip library before sending.
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight the archive with a conformant unzip before importing.
import { execFileSync } from 'node:child_process';
function zipIsSound(file: string): boolean {
try {
execFileSync('unzip', ['-tqq', file], { stdio: 'ignore' });
return true;
} catch {
return false;
}
}
if (!zipIsSound(uploadPath)) return res.status(400).json({ error: 'corrupt zip' }); Try / catch
// importClaudeDesignZip throws a plain Error; catch at the route/caller.
try {
const imported = await importClaudeDesignZip(zipPath, projectDir);
} catch (err) {
// All zip-structure errors surface here; the HTTP route returns 400.
return res.status(400).json({ error: String(err) });
} Prevention
- Run `unzip -t` on every uploaded zip before calling importClaudeDesignZip.
- Reject uploads whose declared size doesn't match the received size.
- Regenerate zips only with standard tools (Info-ZIP, Finder, Windows Explorer).
When it happens
Trigger: Calling importClaudeDesignZip (or uploading a multipart 'file' to POST /api/import/claude-design) on a zip whose central directory is malformed: a truncated archive, an entry whose declared name/extra/comment lengths push the next offset into invalid data, or a central directory that was copied from a different archive.
Common situations: A file renamed to .zip that isn't a real archive; a partially downloaded/uploaded zip; a zip produced by a non-conformant packager; corruption introduced by a proxy/CDN truncating the multipart upload; a zip edited after creation.
Related errors
- zip entry size mismatch: ${relPath}
- zip contains no files
- zip does not contain an HTML file
- invalid zip central directory
- invalid zip: missing central directory
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/bbf9496136b06643.
Report an issue: GitHub.