nextlevelbuilder/ui-ux-pro-max-skill · error · Error
Failed to extract zip: ${error}
Error message
Failed to extract zip: ${error} What it means
extractZip() shells out to the platform's unzip tool (Expand-Archive on Windows, the `unzip` binary elsewhere) and wraps any non-zero exit in a generic 'Failed to extract zip' error. It fires when the external command itself fails: the tool is missing, the archive is corrupt or not a real zip, or the path contains characters the shell command mangles.
Source
Thrown at cli/src/utils/extract.ts:22
import { promisify } from 'node:util';
import { tmpdir } from 'node:os';
import type { AIType } from '../types/index.js';
import { AI_FOLDERS } from '../types/index.js';
const execAsync = promisify(exec);
const EXCLUDED_FILES = ['settings.local.json'];
export async function extractZip(zipPath: string, destDir: string): Promise<void> {
try {
const isWindows = process.platform === 'win32';
if (isWindows) {
await execAsync(`powershell -Command "Expand-Archive -Path '${zipPath}' -DestinationPath '${destDir}' -Force"`);
} else {
await execAsync(`unzip -o "${zipPath}" -d "${destDir}"`);
}
} catch (error) {
throw new Error(`Failed to extract zip: ${error}`);
}
}
async function exists(path: string): Promise<boolean> {
try {
await access(path);
return true;
} catch {
return false;
}
}
export async function copyFolders(
sourceDir: string,
targetDir: string,
aiType: AIType
): Promise<string[]> {
const copiedFolders: string[] = [];View on GitHub (pinned to a38d04c3d5)
Solutions
- Verify the downloaded file is a real zip: `file release.zip` or check its first bytes are 'PK'.
- Install the missing tool: `apt-get install unzip` (Debian/Alpine: `apk add unzip`) on Linux, or confirm PowerShell 5+ on Windows.
- Re-run the install on a stable network, or retry from a different network if the download was truncated.
- If the temp path contains quotes/spaces, move the operation to a plain path (e.g. TMPDIR without spaces) or replace execAsync with a Node zip library such as yauzl/adm-zip that takes paths as arguments, avoiding shell interpolation entirely.
Example fix
// before
await execAsync(`unzip -o "${zipPath}" -d "${destDir}"`);
// after: no shell interpolation, no external binary
import AdmZip from 'adm-zip';
new AdmZip(zipPath).extractAllTo(destDir, true); Defensive patterns
Strategy: validation
Validate before calling
import { open } from 'node:fs/promises';
import { exec } from 'node:child_process';
async function isRealZip(path: string): Promise<boolean> {
const fh = await open(path, 'r');
try {
const buf = Buffer.alloc(2);
await fh.read(buf, 0, 2, 0);
return buf.toString('ascii') === 'PK';
} finally {
await fh.close();
}
}
function hasUnzip(): Promise<boolean> {
return new Promise(res => exec('unzip -v', err => res(!err)));
} Try / catch
try {
await extractZip(zipPath, destDir);
} catch (e) {
throw new Error(
`Extraction failed on ${process.platform}; zip valid=${await isRealZip(zipPath)}; ` +
`likely missing 'unzip' binary or corrupt download: ${(e as Error).message}`
);
} Prevention
- Install unzip in Dockerfiles that run the CLI (apk add unzip / apt-get install -y unzip).
- Validate the zip magic bytes ('PK') right after download, before extraction.
- Prefer a pure-JS zip library (yauzl, adm-zip) to remove the external-binary dependency and shell-quoting risks entirely.
When it happens
Trigger: `uipro init` reaches the extraction step and: (1) the downloaded release.zip is an HTML error page or truncated because the download was interrupted; (2) on macOS/Linux the `unzip` binary is not installed (minimal containers like alpine node images); (3) a path with spaces/quotes breaks the interpolated shell string; (4) Expand-Archive is unavailable on old Windows PowerShell or the destination is locked.
Common situations: Running the installer inside a slim Docker image that lacks unzip; a proxy/CDN returning a 200 response with an error body; extracting into a directory the user cannot write; zip64 archives that some unzip builds cannot handle.
Related errors
- No ZIP asset found in latest release
- GitHub API rate limit exceeded. Resets at ${resetDate}.\n${g
- Failed to fetch releases: ${response.status} ${response.stat
- Unknown AI type: ${aiType}
- --verified-at is required when generating the summary
AI-assisted analysis of nextlevelbuilder/ui-ux-pro-max-skill@a38d04c3d5 (2026-08-14).
Data as JSON: /api/errors/be74380e889e2b84.
Report an issue: GitHub.