can1357/oh-my-pi · error · Error
Failed to extract ${assetName}: ${err instanceof Error ? err
Error message
Failed to extract ${assetName}: ${err instanceof Error ? err.message : String(err)} What it means
extractArchive() failing (corrupt archive, unsupported compression inside, disk issues) is wrapped by downloadTool() into this error, embedding the asset name and the underlying message. The error chain is preserved so the root cause is visible.
Source
Thrown at packages/coding-agent/src/utils/tools-manager.ts:265
return binaryPath;
}
// Download archive
const archivePath = path.join(TOOLS_DIR, assetName);
await downloadFile(downloadUrl, archivePath, signal);
// Extract
const tmp = await TempDir.create("@omp-tools-extract-");
try {
if (!assetName.endsWith(".tar.gz") && !assetName.endsWith(".zip")) {
throw new Error(`Unsupported archive format: ${assetName}`);
}
try {
await extractArchive(archivePath, tmp.path());
} catch (err) {
throw new Error(`Failed to extract ${assetName}: ${err instanceof Error ? err.message : String(err)}`);
}
// Find the binary in extracted files
// ast-grep releases the binary directly in the zip, not in a subdirectory
let extractedBinary: string;
if (tool === "sg") {
extractedBinary = path.join(tmp.path(), config.binaryName + binaryExt);
} else {
const extractedDir = path.join(tmp.path(), assetName.replace(/\.(tar\.gz|zip)$/, ""));
extractedBinary = path.join(extractedDir, config.binaryName + binaryExt);
}
if (fs.existsSync(extractedBinary)) {
await fs.promises.rename(extractedBinary, binaryPath);
} else {
throw new Error(`Binary not found in archive: ${extractedBinary}`);
}
View on GitHub (pinned to 9690622007)
Solutions
- Read the embedded inner message to identify the root cause (e.g. "invalid zip", "unexpected end of file").
- Delete any cached/partial downloads and retry — a truncated asset is the most common cause.
- Verify the asset's integrity (SHA published by upstream) and confirm the file isn't an HTML error page (file archive.tar.gz).
- Pin to a stable prior release if upstream just re-published a broken asset.
- Check available disk space in the temp/tools directories.
Example fix
// before: await toolsManager.download("fd") // throws "Failed to extract fd-...zip: unexpected EOF" | // after: catch, and if err.message.startsWith("Failed to extract"), clear cache and retry once; rethrow otherwise Defensive patterns
Strategy: retry
Validate before calling
// verify asset integrity before extraction by checking size | const head = await fetch(assetUrl, { method: "HEAD" }); const expectedSize = Number(head.headers.get("content-length") ?? 0); const actualSize = (await fs.stat(localPath)).size; if (actualSize !== expectedSize) throw new Error("Truncated download; refetch"); Type guard
function isExtractionFailure(err: unknown): err is Error { return err instanceof Error && /^Failed to extract .+:/.test(err.message); } Try / catch
try { const p = await toolsManager.download("sg"); } catch (err) { if (isExtractionFailure(err)) { /* delete partial download, retry once, then surface inner cause */ } else throw err; } Prevention
- Verify downloaded sizes/checksums against upstream-published SHAs.
- Ensure adequate free disk space in temp directories.
- Retry once on extraction failure — truncated downloads are the top cause.
- Don't download while a release is actively being re-published.
When it happens
Trigger: The downloaded .tar.gz or .zip asset fails during extractArchive(archivePath, tmp.path()) — truncated/corrupt download, HTML error page saved as an archive (e.g. a 404 body that slipped through), or an archive using an algorithm the extractor rejects.
Common situations: Interrupted downloads from unstable networks, upstream re-releasing/overwriting a release asset mid-download (checksum mismatch), CDN serving an error page, full disk during extraction, or genuine archive corruption.
Related errors
- Archive entry escapes extraction dir: ${entry.path}
- Archive symlink escapes extraction dir: ${link.path} -> ${li
- archive destination exists: ${destSession}
- archive destination exists: ${legacyDestSession}
- archive artifacts destination exists: ${destArtifacts}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/d348b68329f9c2b3.
Report an issue: GitHub.