nexu-io/open-design · error · Error
zip contains no files
Error message
zip contains no files
What it means
Thrown by `importClaudeDesignZip` after the entry loop completes if no decodable file entries were collected (`files.length === 0`). This happens when the archive contains only directory entries, or has no entries at all. There is nothing to import, so the importer fails fast rather than producing an empty project.
Source
Thrown at apps/daemon/src/design/claude-design-import.ts:56
// 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);
}
return pending;
};
await mkdir(projectDir, { recursive: true });
await Promise.all(files.map(async (f) => {
const target = safeJoin(projectDir, f.path);
await ensureDir(path.dirname(target));
await writeFile(target, f.body);View on GitHub (pinned to 5be4028344)
Solutions
- Re-create the archive ensuring it contains at least one real file entry.
- Verify the source export actually produced files; re-export if necessary.
- Check that the zip tool did not store files as directory-only entries.
Defensive patterns
Strategy: validation
Validate before calling
const fileEntries = entries.filter((e) => !e.isDirectory);
if (fileEntries.length === 0) {
throw new Error('archive contains no file entries');
} Try / catch
try {
await importClaudeDesignZip(zipPath, projectDir);
} catch (err) {
if (err instanceof Error && err.message === 'zip contains no files') {
// re-create the archive with at least one real file
}
throw err;
} Prevention
- Ensure the source export actually contains files before zipping.
- Verify the archive includes file entries (not only directories) before uploading.
- Reject empty archives at the request layer.
When it happens
Trigger: Uploading an empty zip. Uploading a zip that contains only directory entries (all entries end with `/`). An archive whose entries were all filtered out as directories.
Common situations: An empty or placeholder archive. A zip created by accidentally zipping a folder's structure without its files. A tool that emitted directory entries but skipped file payloads.
Related errors
- zip entry size mismatch: ${relPath}
- zip does not contain an HTML file
- invalid zip central directory
- 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/574688f331a3f007.
Report an issue: GitHub.