nexu-io/open-design · error · Error
zip entry size mismatch: ${relPath}
Error message
zip entry size mismatch: ${relPath} What it means
Thrown by `importClaudeDesignZip` when an entry's central-directory-declared `uncompressedSize` is greater than 0 but does not equal the actual decoded body length. This catches truncated, corrupt, or tampered entries where the declared size and the real payload disagree.
Source
Thrown at apps/daemon/src/design/claude-design-import.ts:48
for (const entry of entries) {
if (entry.isDirectory) continue;
if (files.length >= MAX_FILES) throw new Error('zip contains too many files');
const relPath = sanitizeZipPath(entry.name);
if (entry.uncompressedSize > MAX_FILE_BYTES) {
throw new Error(`zip file too large: ${relPath}`);
}
// Decode first; the central directory's uncompressedSize is unreliable for
// streaming/data-descriptor zips (it can read 0 even when the payload
// carries real data). The inflate cap and the post-decode size checks below
// are authoritative.
const body = readEntryBody(zip, entry);
if (body.length > MAX_FILE_BYTES) {
throw new Error(`zip file too large: ${relPath}`);
}
if (entry.uncompressedSize > 0 && body.length !== entry.uncompressedSize) {
throw new Error(`zip entry size mismatch: ${relPath}`);
}
totalBytes += body.length;
if (totalBytes > MAX_TOTAL_BYTES) throw new Error('zip is too large');
files.push({ path: relPath, body: normalizeImportedClaudeDesignFile(relPath, body) });
}
if (files.length === 0) throw new Error('zip contains no files');
const entryFile = chooseEntryFile(files.map((f) => f.path));
if (!entryFile) throw new Error('zip does not contain an HTML file');
const dirCreates = new Map<string, Promise<string | undefined>>();
const ensureDir = (dir: string) => {
let pending = dirCreates.get(dir);
if (!pending) {
pending = mkdir(dir, { recursive: true });
dirCreates.set(dir, pending);
}View on GitHub (pinned to 5be4028344)
Solutions
- Re-obtain the zip from the original source (re-export or re-download) to rule out truncation/corruption.
- Verify the archive with a standard unzip tool; if it reports an error, the archive is corrupt.
- If you produce the archive, ensure the writer emits correct uncompressed sizes.
Defensive patterns
Strategy: validation
Validate before calling
for (const entry of entries.filter((e) => !e.isDirectory && e.uncompressedSize > 0)) {
const body = readEntryBody(zip, entry);
if (body.length !== entry.uncompressedSize) {
throw new Error(`entry "${entry.name}" decoded size ${body.length} != declared ${entry.uncompressedSize}`);
}
} Try / catch
try {
await importClaudeDesignZip(zipPath, projectDir);
} catch (err) {
if (err instanceof Error && /^zip entry size mismatch:/.test(err.message)) {
// re-obtain the archive; it is corrupt or truncated
}
throw err;
} Prevention
- Re-obtain archives from the original source to avoid truncation/corruption.
- Verify archives with a standard unzip tool before importing.
- Use a reliable zip writer that emits correct uncompressed sizes.
When it happens
Trigger: A zip entry whose declared uncompressed size is, say, 1024 bytes but whose decoded body is a different length. Causes include a truncated download, a corrupt archive, a tampered central directory, or a zip produced by a buggy writer.
Common situations: The archive was partially downloaded or transferred. Disk corruption. A zip writer bug. An attacker altering the central directory to disguise a large payload.
Related errors
- invalid zip central directory
- zip contains no files
- zip does not contain an HTML file
- invalid zip central directory entry
- zip entry exceeds archive: ${entry.name}
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/151c318002177236.
Report an issue: GitHub.