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

  1. Read the embedded inner message to identify the root cause (e.g. "invalid zip", "unexpected end of file").
  2. Delete any cached/partial downloads and retry — a truncated asset is the most common cause.
  3. Verify the asset's integrity (SHA published by upstream) and confirm the file isn't an HTML error page (file archive.tar.gz).
  4. Pin to a stable prior release if upstream just re-published a broken asset.
  5. 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

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


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d348b68329f9c2b3. Report an issue: GitHub.