ruvnet/ruflo · error · ExtractionError
zip extraction failed via both available extractors…
Error message
zip extraction failed via both available extractors. Expand-Archive: ${primaryMessage} — tar fallback: ${fallbackMessage} What it means
The Windows .zip extraction path is two-stage: Expand-Archive first, then bsdtar `tar xf` as fallback (zip is not gzip-compressed, hence 'xf' and format sniffing). When BOTH fail, install throws ExtractionError concatenating the primary (PowerShell) and fallback (tar) messages. The two embedded messages are the diagnostic — together they tell you whether the problem is the archive itself (both fail on corruption) or the machine (PowerShell policy + missing tar.exe).
Solutions
- Split the message at the ' — tar fallback:' marker: fix the PowerShell half (execution policy / module path) or the tar half (install bsdtar / use Windows 10+).
- If both messages show corruption ('not a valid archive', 'unexpected end'), clear the installer work/cache dir and re-run for a fresh download.
- Verify the zip manually: right-click Extract-All or `tar -tf archive.zip` to see which stage is at fault.
- Free disk space and rule out AV locks on the extraction directory.
Example fix
# before: both extractors unavailable -> combined error, install aborts # after: make ONE extractor healthy PS> Set-ExecutionPolicy -Scope CurrentUser RemoteSigned # fixes Expand-Archive # or ensure C:\Windows\System32\tar.exe exists (Windows 10 1803+) # fixes fallback PS> claude-flow install
Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight on Windows before proxy install:
const extractors = [expandArchiveWorks, tarAvailable].map(f => f()).filter(Boolean).length;
if (extractors === 0) {
throw new Error('no usable zip extractor: enable Expand-Archive (execution policy) or install tar.exe');
}
// >= 1 means the combined both-extractors failure cannot happen for environment reasons; only archive corruption remains. Type guard
function isBothExtractorsError(e: unknown): e is Error {
return e instanceof Error && e.message.startsWith('zip extraction failed via both available extractors');
} Try / catch
for (let attempt = 1; ; attempt++) {
try {
return await installProxyBinary({ version });
} catch (e) {
if (attempt < 3 && isBothExtractorsError(e)) {
await cleanWorkDir(); // both extractors failing usually means a corrupt download — fetch fresh
continue;
}
if (isBothExtractorsError(e)) {
const [, primary, fallback] = e.message.split(/ — tar fallback: /);
throw new Error(`install blocked: fix extractor environment. PowerShell: ${primary}. tar: ${fallback}`);
}
throw e;
}
} Prevention
- Keep BOTH Windows extractors serviceable so one failure never becomes total: execution policy + tar.exe.
- Validate downloaded assets (size/checksum if published) before extraction to catch truncation early.
- On failure, always read the two embedded messages separately — they usually have different root causes.
When it happens
Trigger: A corrupted/truncated .zip download fails in both extractors; or a stripped-down Windows environment where Expand-Archive is blocked (execution policy) AND tar.exe is absent/older-than-Windows-10 — both stages then fail for different reasons, and both messages appear in the thrown error.
Common situations: Hardened Windows Server images with Restricted execution policy and no bsdtar; interrupted proxy binary downloads (network dropped mid-asset); CI Windows runners with damaged PowerShell module paths plus no tar on PATH; destination disk full so every extractor exits non-zero.
Related errors
- Expand-Archive failed
- tar extraction failed
- archive did not contain the expected binary at its root
- Previous Meta-Proxy .
- Rollback failed
AI-assisted analysis of ruvnet/ruflo@29f048fc3b (2026-08-18).
Data as JSON: /api/errors/40b7870f7b89ecbe.
Report an issue: GitHub.
Appendix: source
Thrown at v3/@claude-flow/cli/src/proxy/install.ts:99
*/
export async function extractArchive(archivePath: string, extractDir: string, ext: 'zip' | 'tar.gz'): Promise<void> {
fs.mkdirSync(extractDir, { recursive: true });
if (ext === 'tar.gz') {
await extractWithTar(archivePath, extractDir, 'xzf');
return;
}
try {
await extractWithPowerShell(archivePath, extractDir);
} catch (primary) {
const primaryMessage = primary instanceof Error ? primary.message : String(primary);
try {
// 'xf', not 'xzf' — a zip is not gzip-compressed; bsdtar sniffs the format.
await extractWithTar(archivePath, extractDir, 'xf');
} catch (fallback) {
const fallbackMessage = fallback instanceof Error ? fallback.message : String(fallback);
throw new ExtractionError(
`zip extraction failed via both available extractors. Expand-Archive: ${primaryMessage} — tar fallback: ${fallbackMessage}`,
);
}
}
}
export interface InstallOptions {
version: string;
log?: (line: string) => void;
}
export interface InstallResult {
version: string;
binaryPath: string;
sha256: string;
}
/**View on GitHub (pinned to 29f048fc3b)