{"record":{"id":"48877b9bae574aae","repo":"ruvnet/ruflo","slug":"tar-extraction-failed-exit-result-exitcode","errorCode":null,"errorMessage":"tar extraction failed (exit ${result.exitCode}): ${result.stderr || result.stdout}","messagePattern":"tar extraction failed \\(exit (.+?)\\): (.+?)","errorType":"exception","errorClass":"ExtractionError","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli/src/proxy/install.ts","lineNumber":36,"sourceCode":"\nexport class ExtractionError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = 'ExtractionError';\n  }\n}\n\nfunction binaryNameInArchive(): string {\n  return process.platform === 'win32' ? 'meta-proxy.exe' : 'meta-proxy';\n}\n\n/** `tar` handles `.tar.gz` everywhere, and `.zip` via bsdtar on Windows 10+. */\nasync function extractWithTar(archivePath: string, extractDir: string, flags: 'xzf' | 'xf'): Promise<void> {\n  const { SafeExecutor } = await import('@claude-flow/security');\n  const exec = new SafeExecutor({ allowedCommands: ['tar'], timeout: 60_000 });\n  const result = await exec.execute('tar', [flags, archivePath, '-C', extractDir]);\n  if (result.exitCode !== 0) {\n    throw new ExtractionError(`tar extraction failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n  }\n}\n\n/**\n * Single-quoted literal paths (doubling any embedded single quote per\n * PowerShell string-literal escaping) passed as ONE argv element to\n * `-Command`. shell:false means no OS shell ever tokenizes this string —\n * only powershell.exe's own parser does.\n */\nasync function extractWithPowerShell(archivePath: string, extractDir: string): Promise<void> {\n  const { SafeExecutor } = await import('@claude-flow/security');\n  const escape = (p: string) => p.replace(/'/g, \"''\");\n  const command = `Expand-Archive -LiteralPath '${escape(archivePath)}' -DestinationPath '${escape(extractDir)}' -Force`;\n  const exec = new SafeExecutor({ allowedCommands: ['powershell', 'powershell.exe'], timeout: 60_000 });\n  const result = await exec.execute('powershell', ['-NoProfile', '-NonInteractive', '-Command', command]);\n  if (result.exitCode !== 0) {\n    throw new ExtractionError(`Expand-Archive failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);\n  }","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/ruvnet/ruflo/blob/29f048fc3b556f857cf2b126d2a84c19d2daa0d0/v3/@claude-flow/cli/src/proxy/install.ts#L18-L54","documentation":"During meta-proxy binary installation, .tar.gz (and zip-fallback) extraction shells out to `tar` through SafeExecutor (60s timeout, allowlist ['tar']). A non-zero exit code throws ExtractionError with the code plus tar's stderr/stdout. The archive was downloaded into a work directory first, so the failure is about extraction, not the download itself — typically a truncated/corrupt archive, missing tar binary, disk full, or permission problems on the extract directory.","triggerScenarios":"install runs `tar xzf <archive> -C <extractDir>` and tar exits non-zero: gzip corruption from a partially downloaded asset ('unexpected end of file'), 'tar: command not found' variant (exit 127 via executor), no space left on device, read-only extract dir, or extraction exceeding the 60s SafeExecutor timeout on huge archives/slow disks.","commonSituations":"Flaky network producing truncated downloads; minimal Docker images (slim/distroless) without tar; CI runners with full disks; Windows boxes older than Windows 10 (no bsdtar); aggressive antivirus locking the archive mid-extraction on Windows.","solutions":["Read the embedded stderr in the message — tar states the exact problem (corrupt gzip, permissions, space).","Free disk space / fix permissions on the install work directory, then re-run install (it re-downloads).","Ensure `tar` exists on PATH (Windows 10+ ships bsdtar; Linux/macOS always do; slim containers need the tar package added).","If corruption is suspected, clear the installer's work/cache directory so a fresh archive is downloaded."],"exampleFix":"# before: slim container without tar -> exit 127 -> ExtractionError\nFROM node:22-slim\nRUN claude-flow-proxy-install\n\n# after\nFROM node:22-slim\nRUN apt-get update && apt-get install -y tar && rm -rf /var/lib/apt/lists/*\nRUN claude-flow-proxy-install","handlingStrategy":"retry","validationCode":"import { execFileSync } from 'node:child_process';\nfunction tarAvailable(): boolean {\n  try { execFileSync('tar', ['--version'], { stdio: 'ignore' }); return true; } catch { return false; }\n}\n// Before triggering proxy install:\nif (!tarAvailable()) throw new Error('tar not on PATH — install it (apt-get install tar / use Windows 10+) before proxy install');","typeGuard":"function isExtractionError(e: unknown): e is Error {\n  return e instanceof Error && /tar extraction failed \\(exit \\d+\\)/.test(e.message);\n}","tryCatchPattern":"for (let attempt = 1; ; attempt++) {\n  try {\n    return await installProxyBinary({ version });\n  } catch (e) {\n    if (attempt < 3 && isExtractionError(e)) {\n      await cleanWorkDir(); // drop the possibly-truncated archive so the retry re-downloads\n      continue;\n    }\n    if (isExtractionError(e)) throw new Error(`proxy install failed after retries: ${e.message}`);\n    throw e;\n  }\n}","preventionTips":["Verify tar exists in the runtime image before depending on proxy install.","Ensure the install work directory is writable and has free space.","Clean partial downloads between attempts — re-extracting the same corrupt archive always fails the same way."],"tags":["proxy","install","tar","extraction","subprocess"],"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"}