laurent22/joplin · error · Error
Extracting ${outPath} would overwrite
Error message
Extracting ${outPath} would overwrite What it means
Thrown during tar entry processing when the resolved output path for an entry already exists on disk. tarExtract treats extraction as non-destructive: it refuses to overwrite anything already present in the cwd target directory. The path is first sanitized through fsDriver.resolveRelativePathWithinDir(cwd, header.name) to prevent path traversal, then existence is checked.
Source
Thrown at packages/app-mobile/utils/fs-driver/tarExtract.ts:30
const cwd = options.cwd;
// resolve doesn't correctly handle file:// or content:// URLs. Thus, we don't resolve relative
// to cwd if the source is a URL.
const isSourceUrl = options.file.match(/$[a-z]+:\/\//);
const filePath = isSourceUrl ? options.file : resolve(cwd, options.file);
const fsDriver = shim.fsDriver();
if (!(await fsDriver.exists(filePath))) {
throw new Error('tarExtract: Source file does not exist');
}
const extract = tarStreamExtract({ defaultEncoding: 'base64' });
extract.on('entry', async (header, stream, next) => {
const outPath = fsDriver.resolveRelativePathWithinDir(cwd, header.name);
if (await fsDriver.exists(outPath)) {
throw new Error(`Extracting ${outPath} would overwrite`);
}
// Allows moving to the next item after all data for this entry has been read
// **and** this data has been processed.
// See https://github.com/laurent22/joplin/issues/10285
const streamEndPromise = new Promise<void>((resolve) => {
stream.once('end', () => resolve());
});
if (header.type === 'directory') {
await fsDriver.mkdir(outPath);
} else if (header.type === 'file') {
const parentDir = dirname(outPath);
await fsDriver.mkdir(parentDir);
await fsDriver.appendBinaryReadableToFile(outPath, stream);
} else {
throw new Error(`Unsupported file system entity type: ${header.type}`);View on GitHub (pinned to 2654b33620)
Solutions
- Clean or use a fresh empty directory as cwd before extracting: await shim.fsDriver().removeAllDir(cwd); await shim.fsDriver().mkdir(cwd).
- If re-extraction is intentional, delete the specific colliding paths first.
- Inspect the tar's entry list (tar -tf on desktop) to find which entry name collides with outPath in the error message.
- Ensure the caller does not extract into the live resource directory without prior eviction.
Example fix
// before
tarExtract({ cwd: targetDir, file: archive });
// after — ensure a clean target
if (await shim.fsDriver().exists(targetDir)) {
await shim.fsDriver().removeAllDir(targetDir);
}
await shim.fsDriver().mkdir(targetDir);
tarExtract({ cwd: targetDir, file: archive }); Defensive patterns
Strategy: validation
Validate before calling
const fsDriver = shim.fsDriver();
// Ensure cwd is empty or pre-cleaned before extraction
const entries = await fsDriver.readDirStats(options.cwd);
if (entries.length > 0) {
await fsDriver.removeAllDir(options.cwd);
await fsDriver.mkdir(options.cwd);
}
await tarExtract(options); Type guard
function isCleanDir(stats) { return stats.length === 0; } Try / catch
try {
await tarExtract(options);
} catch (e) {
if (/Extracting .* would overwrite/.test(e.message)) {
const p = e.message.match(/Extracting (.*) would overwrite/)?.[1];
await shim.fsDriver().remove(p);
await tarExtract(options); // retry once
} else throw e;
} Prevention
- Extract into a freshly created empty directory.
- Never extract into the live resource directory without eviction.
- Keep the archive's entry list free of name collisions.
When it happens
Trigger: Extracting a tar into a cwd that already contains files/dirs with the same names; a previous interrupted extraction left partial files; extracting the same archive twice; the tar contains entries whose header.name collide with pre-existing user data in cwd.
Common situations: Re-running a backup restore into a non-empty directory; the restore target was not cleaned between attempts; a sync conflict deposited files with identical names; tar was built with absolute or duplicated entry names that collapse onto the same target.
Related errors
- Error! Destination already exists
- tarExtract: Source file does not exist
- Unsupported file system entity type: ${header.type}
- No model found at path: ${JSON.stringify(modelFolderPath)}
- Model not found at path ${modelPath}
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/fcc154b7195f7e94.
Report an issue: GitHub.