{"record":{"id":"40b7870f7b89ecbe","repo":"ruvnet/ruflo","slug":"zip-extraction-failed-via-both-available-extractor","errorCode":null,"errorMessage":"zip extraction failed via both available extractors. Expand-Archive: ${primaryMessage} — tar fallback: ${fallbackMessage}","messagePattern":"zip extraction failed via both available extractors\\. Expand-Archive: (.+?) — tar fallback: (.+?)","errorType":"exception","errorClass":"ExtractionError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/proxy/install.ts","lineNumber":99,"sourceCode":" */\nexport async function extractArchive(archivePath: string, extractDir: string, ext: 'zip' | 'tar.gz'): Promise<void> {\n  fs.mkdirSync(extractDir, { recursive: true });\n\n  if (ext === 'tar.gz') {\n    await extractWithTar(archivePath, extractDir, 'xzf');\n    return;\n  }\n\n  try {\n    await extractWithPowerShell(archivePath, extractDir);\n  } catch (primary) {\n    const primaryMessage = primary instanceof Error ? primary.message : String(primary);\n    try {\n      // 'xf', not 'xzf' — a zip is not gzip-compressed; bsdtar sniffs the format.\n      await extractWithTar(archivePath, extractDir, 'xf');\n    } catch (fallback) {\n      const fallbackMessage = fallback instanceof Error ? fallback.message : String(fallback);\n      throw new ExtractionError(\n        `zip extraction failed via both available extractors. Expand-Archive: ${primaryMessage} — tar fallback: ${fallbackMessage}`,\n      );\n    }\n  }\n}\n\nexport interface InstallOptions {\n  version: string;\n  log?: (line: string) => void;\n}\n\nexport interface InstallResult {\n  version: string;\n  binaryPath: string;\n  sha256: string;\n}\n\n/**","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/ruvnet/ruflo/blob/29f048fc3b556f857cf2b126d2a84c19d2daa0d0/v3/@claude-flow/cli/src/proxy/install.ts#L81-L117","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before: both extractors unavailable -> combined error, install aborts\n# after: make ONE extractor healthy\nPS> Set-ExecutionPolicy -Scope CurrentUser RemoteSigned   # fixes Expand-Archive\n# or ensure C:\\Windows\\System32\\tar.exe exists (Windows 10 1803+)  # fixes fallback\nPS> claude-flow install","handlingStrategy":"retry","validationCode":"// Pre-flight on Windows before proxy install:\nconst extractors = [expandArchiveWorks, tarAvailable].map(f => f()).filter(Boolean).length;\nif (extractors === 0) {\n  throw new Error('no usable zip extractor: enable Expand-Archive (execution policy) or install tar.exe');\n}\n// >= 1 means the combined both-extractors failure cannot happen for environment reasons; only archive corruption remains.","typeGuard":"function isBothExtractorsError(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('zip extraction failed via both available extractors');\n}","tryCatchPattern":"for (let attempt = 1; ; attempt++) {\n  try {\n    return await installProxyBinary({ version });\n  } catch (e) {\n    if (attempt < 3 && isBothExtractorsError(e)) {\n      await cleanWorkDir(); // both extractors failing usually means a corrupt download — fetch fresh\n      continue;\n    }\n    if (isBothExtractorsError(e)) {\n      const [, primary, fallback] = e.message.split(/ — tar fallback: /);\n      throw new Error(`install blocked: fix extractor environment. PowerShell: ${primary}. tar: ${fallback}`);\n    }\n    throw e;\n  }\n}","preventionTips":["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."],"tags":["proxy","install","windows","zip","extraction","fallback"],"backgroundTag":"archive-extraction-failed","analyzedSha":"29f048fc3b556f857cf2b126d2a84c19d2daa0d0","analyzedAt":"2026-08-18T21:34:22.708Z","contentChangedAt":"2026-08-18T21:34:22.708Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}