{"record":{"id":"118464dfcbbc3dc4","repo":"coleam00/Archon","slug":"tar-extraction-failed-exit-exitcode-detail","errorCode":null,"errorMessage":"tar extraction failed (exit ${exitCode}): ${details}","messagePattern":"tar extraction failed \\(exit (.+?)\\): (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/serve.ts","lineNumber":253,"sourceCode":"        signalCode: proc.signalCode,\n        durationMs: Math.round(extractionEndedAt - spawnedAt),\n      },\n      'web_dist.extract_exited'\n    );\n    const details = stderrText.trim();\n    // A signal means `tar` never finished. `proc.killed` cannot say so — it is\n    // true after any exit — and a signal can also come from outside this process,\n    // so report how long it actually ran instead of asserting the bound fired.\n    if (proc.signalCode !== null) {\n      const elapsedMs = Math.round(extractionEndedAt - extractionStartedAt);\n      cleanupAndThrow(\n        tmpDir,\n        `tar extraction was killed by ${proc.signalCode} after ${elapsedMs}ms without finishing ` +\n          `(limit ${EXTRACTION_TIMEOUT_MS}ms): ${details}`\n      );\n    }\n    if (exitCode !== 0) {\n      cleanupAndThrow(tmpDir, `tar extraction failed (exit ${exitCode}): ${details}`);\n    }\n  } finally {\n    rmSync(tarballPath, { force: true });\n  }\n\n  // Verify extraction produced expected layout\n  if (!existsSync(`${tmpDir}/index.html`)) {\n    cleanupAndThrow(\n      tmpDir,\n      'Extraction produced unexpected layout — index.html not found in extracted dir'\n    );\n  }\n\n  // Atomic move into place\n  mkdirSync(dirname(targetDir), { recursive: true });\n  try {\n    renameSync(tmpDir, targetDir);\n  } catch (err) {","sourceCodeStart":235,"sourceCodeEnd":271,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/cli/src/commands/serve.ts#L235-L271","documentation":"downloadWebDist extracts the verified tarball by shelling out to the system `tar` binary with a timeout; cleanupAndThrow removes the temp dir and raises this error when tar exits non-zero. It includes the exit code and captured stderr/stdout details to explain why extraction failed. A kill by signal (e.g. timeout) is reported separately with a distinct message.","triggerScenarios":"serveCommand -> downloadWebDist spawns `tar` on the downloaded archive; the process finishes with exitCode !== 0: corrupted archive despite a valid checksum path, unsupported tar flags on the platform (e.g. BSD vs GNU tar), disk full, permission errors in temp dir, or archive containing paths tar refuses to write.","commonSituations":"Non-GNU tar (macOS bsdtar, busybox tar) rejecting a GNU-specific flag; TMPDIR on a full or noexec filesystem; tarball produced by a newer packaging script with options the installed tar doesn't support; antivirus locking files during extraction.","solutions":["Read `details` in the message — it contains tar's stderr; fix the underlying cause it names (permissions, disk space, bad flag).","Check the installed tar (`tar --version`) and ensure a modern GNU tar or compatible bsdtar is on PATH.","Free disk space and confirm TMPDIR points to a writable, non-noexec location.","Re-download the tarball if details suggest a corrupt archive, then retry serve."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { execSync } from 'node:child_process';\nconst version = execSync('tar --version', { encoding: 'utf8' });\nif (!/GNU tar|bsdtar/.test(version)) {\n  throw new Error(`Unsupported tar on PATH: ${version.split('\\n')[0]}; install GNU tar before serving`);\n}\n// and check tmp writability + free space\nimport { statfsSync } from 'node:fs';\nconst { bavail, bsize } = statfsSync(tmpParent);\nif (bavail * bsize < 512 * 1024 * 1024) throw new Error('Less than 512MB free in TMPDIR');","typeGuard":null,"tryCatchPattern":"try {\n  await serveCommand();\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('tar extraction failed')) {\n    // read the captured tar stderr after 'exit N:'; fix disk/permissions/flag\n    // issue it names, then re-run serve.\n  } else throw err;\n}","preventionTips":["Keep a modern GNU tar (or compatible bsdtar) first on PATH in containers and CI images.","Point TMPDIR at a writable, sufficiently large, non-noexec filesystem.","Test extraction of the exact artifact once in your environment before automating serve.","Watch disk space on the partition hosting TMPDIR."],"tags":["filesystem","tar","subprocess","extraction"],"backgroundTag":"tar-extraction-failed","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}