n8n-io/n8n · error · Error
Tarball not found
Error message
Tarball not found
What it means
Thrown by downloadAndExtractPackage when `npm pack` reported success (status 0) but no file ending in .tgz is present in TEMP_DIR. The scanner keys entirely off the .tgz extension, so any pack output that names the file differently (or writes elsewhere) breaks extraction before it starts.
Source
Thrown at packages/@n8n/scan-community-package/scanner/scanner.mjs:93
// Handle regular packages
const parts = packageSpec.split('@');
return { packageName: parts[0], version: parts[1] || null };
};
const downloadAndExtractPackage = async (packageName, version) => {
try {
// Download the tarball using safe arguments
const npmResult = spawnSync('npm', ['-q', 'pack', `${packageName}@${version}`], {
cwd: TEMP_DIR,
stdio: 'pipe',
shell: process.platform === 'win32',
});
if (npmResult.status !== 0) {
throw new Error(`npm pack failed: ${npmResult.stderr?.toString()}`);
}
const tarballName = fs.readdirSync(TEMP_DIR).find((file) => file.endsWith('.tgz'));
if (!tarballName) {
throw new Error('Tarball not found');
}
// Unpack the tarball
const packageDir = safeJoinPath(TEMP_DIR, `${packageName}-${version}`);
fs.mkdirSync(packageDir, { recursive: true });
const tarResult = spawnSync(
'tar',
['-xzf', tarballName, '-C', packageDir, '--strip-components=1'],
{
cwd: TEMP_DIR,
stdio: 'pipe',
shell: process.platform === 'win32',
},
);
if (tarResult.status !== 0) {
throw new Error(`tar extraction failed: ${tarResult.stderr?.toString()}`);
}
fs.unlinkSync(safeJoinPath(TEMP_DIR, tarballName));View on GitHub (pinned to 5ac6606e81)
Solutions
- Ensure TEMP_DIR is a private, freshly created directory per scan invocation (mkdtemp) so no other process can consume the .tgz.
- Pin the npm version used by the scanner so pack output location is stable.
- Parse the tarball filename from npm pack's stdout (npm pack prints the filename) instead of globbing TEMP_DIR.
- Disable concurrent scans against the same TEMP_DIR.
Example fix
// before
const npmResult = spawnSync('npm', ['-q', 'pack', `${packageName}@${version}`], { cwd: TEMP_DIR });
const tarballName = fs.readdirSync(TEMP_DIR).find((f) => f.endsWith('.tgz'));
// after - capture the filename npm pack prints
const npmResult = spawnSync('npm', ['pack', `${packageName}@${version}`], { cwd: TEMP_DIR, encoding: 'utf8' });
const tarballName = npmResult.stdout.trim().split(/\r?\n/).pop();
if (!tarballName || !tarballName.endsWith('.tgz')) throw new Error('Tarball not found'); Defensive patterns
Strategy: validation
Validate before calling
import fs from 'node:fs';
import path from 'node:path';
function ensureFreshTempDir(): string {
const dir = fs.mkdtempSync(path.join(require('os').tmpdir(), 'n8n-scan-'));
return dir;
}
// use a private mkdtemp dir per scan so no other process can race for the .tgz Try / catch
const tarballName = fs.readdirSync(TEMP_DIR).find((f) => f.endsWith('.tgz'));
if (!tarballName) {
const contents = fs.readdirSync(TEMP_DIR);
throw new Error(`Tarball not found after npm pack; TEMP_DIR contents: ${JSON.stringify(contents)}`);
} Prevention
- Use mkdtempSync to give each scan a private TEMP_DIR - eliminates cross-scan races for the .tgz.
- Parse the tarball filename from `npm pack`'s stdout instead of globbing the directory, so a stray file cannot confuse the scanner.
- Disable concurrent scanner invocations against a shared TEMP_DIR.
- If npm version changes, re-verify the pack output filename convention.
When it happens
Trigger: npm pack wrote the tarball to a different cwd than TEMP_DIR; an older/newer npm version prints to a different location; TEMP_DIR was cleared between the pack and the readdirSync; a leftover .tgz from a prior run was already consumed and npm wrote a file the scanner's filter misses.
Common situations: TEMP_DIR misconfigured or pointing at a node_modules symlink that resolves elsewhere; running scans concurrently against the same TEMP_DIR so two runs race for the .tgz; an npm version that emits '.tgz' with unexpected casing; an antivirus/quarantine removing the .tgz immediately after creation.
Related errors
- Path traversal detected, refusing to join paths: ${parentPat
- npm pack failed: ${npmResult.stderr?.toString()}
- tar extraction failed: ${tarResult.stderr?.toString()}
- No version found matching ${version}
- No pending tool call found for toolCallId: ${resumedId}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/1a1d528d99796a60.
Report an issue: GitHub.