cube-js/cube · warning
tar skipped an entry (${code}): ${message}
Error message
tar skipped an entry (${code}): ${message} What it means
During `PackageFetcher.downloadPackages()`, the GitHub repo archive (master.tar.gz) is extracted with node-tar's `tar.x`. Tar does not fail the extraction when an entry is unsafe (paths escaping cwd via `..` or absolute paths) — instead it emits a warning via `onwarn` with codes like TAR_BAD_ENTRIES / TAR_ENTRY_INVALID and silently skips the entry. Cube surfaces these warnings on console.warn because skipped entries can mean the extracted template tree is incomplete, which later manifests as a 'No directory found' error or missing packages.
Source
Thrown at packages/cubejs-templates/src/PackageFetcher.ts:70
(await proxyFetch(url)).body.pipe(writer);
return new Promise((resolve, reject) => {
writer.on('finish', resolve as () => void);
writer.on('error', reject);
});
}
public async downloadPackages() {
await this.downloadRepo();
// Only ever a gzipped tar (GitHub's /archive/<ref>.tar.gz). `tar.x` refuses to
// write outside `cwd`: a leading `/` is stripped on extraction and entries containing `..` are
// dropped — but dropped with a warning rather than an error, so surface it.
await tar.x({
file: this.repoArchivePath,
cwd: this.tmpFolderPath,
preserveOwner: false,
onwarn: (code, message) => console.warn(`tar skipped an entry (${code}): ${message}`),
});
const dir = fs.readdirSync(this.tmpFolderPath).find((name) => !name.endsWith('tar.gz'));
if (!dir) {
throw new Error('No directory found');
}
fs.removeSync(path.resolve(this.tmpFolderPath, dir, 'yarn.lock'));
await executeCommand('npm', ['install'], { cwd: path.resolve(this.tmpFolderPath, dir) });
return {
packagesPath: path.join(this.tmpFolderPath, dir, 'packages'),
};
}
public cleanup() {
fs.removeSync(this.tmpFolderPath);View on GitHub (pinned to 7d981676b3)
Solutions
- Re-download a fresh archive: delete node_modules/.tmp (or run cleanup) so the stale/corrupt master.tar.gz is fetched again.
- Check the console.warn output for the tar code and the skipped entry path to identify which entry is unsafe and why.
- Verify the archive is intact: `tar -tzf node_modules/.tmp/master.tar.gz` and inspect any suspicious paths (leading `/`, `..`).
- Ensure network path (proxy/VPN) is not intercepting/rewriting the GitHub archive download.
- Upgrade @cubejs-backend/templates / node-tar to pick up fixes for entry handling, and retry the scaffolding command.
Example fix
// before: warnings only, skipped entries silently lose files
await tar.x({ file: this.repoArchivePath, cwd: this.tmpFolderPath, preserveOwner: false,
onwarn: (code, message) => console.warn(`tar skipped an entry (${code}): ${message}`) });
// after: fail hard on skipped entries so the fetcher never proceeds with a partial extraction
await tar.x({ file: this.repoArchivePath, cwd: this.tmpFolderPath, preserveOwner: false,
onwarn: (code, message) => { throw new Error(`tar skipped an entry (${code}): ${message}`); } }); Defensive patterns
Strategy: validation
Validate before calling
import * as tar from 'tar';
import fs from 'fs';
async function validateArchiveSafe(archivePath: string, cwd: string) {
if (!fs.existsSync(archivePath) || fs.statSync(archivePath).size === 0) {
throw new Error(`Archive missing or empty: ${archivePath}`);
}
const unsafe: string[] = [];
await tar.t({ file: archivePath, onReadEntry: (e) => {
const p = e.path.replace(/^\//, '');
if (p.includes('..') || e.path.startsWith('/')) unsafe.push(e.path);
}});
if (unsafe.length) throw new Error(`Unsafe tar entries: ${unsafe.join(', ')}`);
} Type guard
function isSafeTarPath(entryPath: string): boolean {
const normalized = entryPath.replace(/^\//, '');
return !normalized.split('/').includes('..') && !entryPath.startsWith('/') && normalized.length > 0;
} Try / catch
try {
await fetcher.downloadPackages();
} catch (err) {
if (err instanceof Error && /No directory found|tar skipped an entry/.test(err.message)) {
// corrupt/unsafe archive: clean and re-fetch
fetcher.cleanup();
await fetcher.downloadPackages();
} else { throw err; }
} Prevention
- Monitor console.warn output during scaffolding — any 'tar skipped an entry' line means files were dropped.
- Delete node_modules/.tmp before retrying so a stale or truncated master.tar.gz is not reused.
- Verify downloaded archives with `tar -tzf` before extraction in CI or custom tooling.
- Pin/upgrade node-tar and @cubejs-backend/templates versions to get fixed entry-handling behavior.
- Avoid proxies that rewrite GitHub archive responses; download over a trusted network.
When it happens
Trigger: Extracting a downloaded repository tarball whose entries are unsafe: archive paths containing `..` segments, absolute paths, or otherwise refused entries that tar drops with a warning instead of an error. In practice this happens with a corrupted, tampered, or unexpectedly structured master.tar.gz downloaded from GitHub.
Common situations: Running `cubejs create` / template scaffolding in environments where a proxy or cache serves a modified/corrupted archive; a GitHub archive format change or symlink-heavy repo producing entries tar refuses; disk/permission issues in node_modules/.tmp causing entries to be skipped.
Related errors
- tar skipped an entry while extracting (${code}): ${message}
- Unable to detect archive format from its contents. Supported
- maskedMembers cannot be provided in the query
- You cannot change security context via __user from ${session
- Unable to find package.json file in current working director
AI-assisted analysis of cube-js/cube@7d981676b3 (2026-09-02).
Data as JSON: /api/errors/ab21a4ff213be707.
Report an issue: GitHub.