{"record":{"id":"49960827b11eaf0a","repo":"n8n-io/n8n","slug":"tar-extraction-failed-tarresult-stderr-tostrin","errorCode":null,"errorMessage":"tar extraction failed: ${tarResult.stderr?.toString()}","messagePattern":"tar extraction failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@n8n/scan-community-package/scanner/scanner.mjs","lineNumber":109,"sourceCode":"\t\tconst tarballName = fs.readdirSync(TEMP_DIR).find((file) => file.endsWith('.tgz'));\n\t\tif (!tarballName) {\n\t\t\tthrow new Error('Tarball not found');\n\t\t}\n\n\t\t// Unpack the tarball\n\t\tconst packageDir = safeJoinPath(TEMP_DIR, `${packageName}-${version}`);\n\t\tfs.mkdirSync(packageDir, { recursive: true });\n\t\tconst tarResult = spawnSync(\n\t\t\t'tar',\n\t\t\t['-xzf', tarballName, '-C', packageDir, '--strip-components=1'],\n\t\t\t{\n\t\t\t\tcwd: TEMP_DIR,\n\t\t\t\tstdio: 'pipe',\n\t\t\t\tshell: process.platform === 'win32',\n\t\t\t},\n\t\t);\n\t\tif (tarResult.status !== 0) {\n\t\t\tthrow new Error(`tar extraction failed: ${tarResult.stderr?.toString()}`);\n\t\t}\n\t\tfs.unlinkSync(safeJoinPath(TEMP_DIR, tarballName));\n\n\t\treturn packageDir;\n\t} catch (error) {\n\t\tconsole.error(`\\nFailed to download package: ${error.message}`);\n\t\tthrow error;\n\t}\n};\n\n/**\n * Extracts the source repository and commit a package was built from, out of\n * its npm provenance attestation. Provenance is already mandatory for the\n * scan to proceed, so any package that reaches this point attests exactly\n * which source produced the published artifact.\n *\n * Returns `{ owner, repo, gitCommit }`, or `null` when the attestation is\n * missing, malformed, or points at an unsupported host.","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/scan-community-package/scanner/scanner.mjs#L91-L127","documentation":"Thrown by downloadAndExtractPackage when the system `tar` binary exits non-zero while extracting a freshly downloaded npm tarball into the per-package directory. Distinct from error 926 (which extracts the source tarball) - this one unpacks the published package itself. The error embeds tar's stderr.","triggerScenarios":"spawnSync('tar', ['-xzf', tarballName, '-C', packageDir, '--strip-components=1']) returns status !== 0 because the tarball is corrupt/truncated, the `tar` binary is missing (common on minimal Windows images), packageDir could not be created, or the tarball uses a format the system tar rejects (e.g. zstd-compressed).","commonSituations":"Running the scanner on a Windows host without `tar` on PATH; CI runner killed mid-download leaving a truncated .tgz; npm registry serving a tarball compressed with an unsupported algorithm; packageDir creation failed silently (read-only TEMP_DIR).","solutions":["Read the embedded tar stderr - 'No such file or directory' means tar is missing; 'Unexpected EOF' means the tarball is truncated.","Install or expose a `tar` binary (bsdtar on Windows via git-for-windows, or tar on Linux/macOS).","Re-run the scan after clearing TEMP_DIR so a stale/truncated .tgz is re-downloaded.","If the registry serves zstd tarballs, use a tar build with zstd support or fall back to Node's tar library."],"exampleFix":"// before\nconst tarResult = spawnSync('tar', ['-xzf', tarballName, '-C', packageDir, '--strip-components=1'], { cwd: TEMP_DIR });\n\n// after - prefer Node tar, fall back to system tar\nimport { extract } from 'tar';\ntry {\n  await extract({ file: safeJoinPath(TEMP_DIR, tarballName), cwd: packageDir, strip: 1 });\n} catch {\n  const tarResult = spawnSync('tar', ['-xzf', tarballName, '-C', packageDir, '--strip-components=1'], { cwd: TEMP_DIR });\n  if (tarResult.status !== 0) throw new Error(`tar extraction failed: ${tarResult.stderr?.toString()}`);\n}","handlingStrategy":"try-catch","validationCode":"import { execFileSync } from 'node:child_process';\n\nfunction tarAvailable(): boolean {\n  try { execFileSync('tar', ['--version'], { stdio: 'pipe' }); return true; }\n  catch { return false; }\n}\n\nif (!tarAvailable()) {\n  throw new Error('tar binary not found; install bsdtar/gnu tar before scanning');\n}","typeGuard":null,"tryCatchPattern":"try {\n  // extraction\n} catch (e) {\n  const stderr = (e as Error).message;\n  if (stderr.includes('Unexpected EOF')) {\n    // truncated download - clear TEMP_DIR and retry once\n    fs.rmSync(TEMP_DIR, { recursive: true, force: true });\n    throw new Error('Tarball truncated; cleared TEMP_DIR for retry');\n  }\n  if (stderr.includes('No such file')) throw new Error('tar binary missing on PATH');\n  throw e;\n}","preventionTips":["Verify a `tar` binary is on PATH before running the scanner (especially on Windows images).","Prefer a Node-native tar (the `tar` npm package) over the system binary for portability.","Clear TEMP_DIR before each scan so a truncated .tgz cannot survive.","Pin the npm version so pack output format is stable."],"tags":["tar","scanner","filesystem","cross-platform"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}