ReactiveX/rxjs · error · Error
Output path already exists; enable overwrite explicitly: ${o
Error message
Output path already exists; enable overwrite explicitly: ${outputPath} What it means
By default the migrator will not overwrite existing output files; this error fires when a planned outputPath already exists as a regular file and the apply options do not include overwrite:true. Re-enabling overwrite is a one-flag opt-in, but the default protects uncommitted work from being clobbered.
Source
Thrown at packages/migrate/src/node.ts:160
for (const { sourcePath, outputPath, result } of plan.files) {
if (result.status === 'refused') throw new Error(`Migration result was refused for source: ${sourcePath}`);
const resolvedOutputPath = resolve(outputPath);
if (resolvedOutputPath === outputRoot) throw new Error(`Output path must identify a file below outputRoot: ${outputPath}`);
assertContained(outputRoot, resolvedOutputPath, `Output path is outside outputRoot: ${outputPath}`);
const canonicalOutputPath = await canonicalFuturePath(resolvedOutputPath);
assertContained(canonicalOutputRoot, canonicalOutputPath, `Output path resolves outside outputRoot: ${outputPath}`);
if (canonicalOutputs.has(canonicalOutputPath)) throw new Error(`Duplicate output path: ${outputPath}`);
canonicalOutputs.add(canonicalOutputPath);
await assertWritableOutput(resolvedOutputPath, options.overwrite ?? false);
}
}
async function assertWritableOutput(outputPath: string, overwrite: boolean): Promise<void> {
try {
const outputStats = await lstat(outputPath);
if (outputStats.isSymbolicLink()) throw new Error(`Refusing to overwrite a symbolic link: ${outputPath}`);
if (!outputStats.isFile()) throw new Error(`Output path is not a regular file: ${outputPath}`);
if (!overwrite) throw new Error(`Output path already exists; enable overwrite explicitly: ${outputPath}`);
} catch (error: unknown) {
if (!isMissingPathError(error)) throw error;
}
}
export async function migrateTestFiles(options: MigrateFilesOptions): Promise<readonly MigratedFile[]> {
if (options.write && !options.outputRoot) {
throw new Error('outputRoot is required when write is enabled.');
}
const plan = await planMigrationFiles(options);
return options.write ? applyMigrationPlan(plan, { overwrite: options.overwrite }) : plan.files;
}
function safeOutputPath(outputRoot: string, outputName: string): string {
if (!outputName || outputName === '.' || isAbsolute(outputName)) {
throw new Error(`Output name must be a non-empty relative path: ${outputName || '<empty>'}`);
}
const outputPath = resolve(outputRoot, outputName);View on GitHub (pinned to 54796b38a5)
Solutions
- Pass overwrite: true in ApplyMigrationPlanOptions / MigrateFilesOptions if regenerating outputs is intended
- Or delete/clean the previous outputs before re-running
- Use a fresh outputRoot per run (e.g. a temp dir) to avoid the collision entirely
Example fix
// before
await migrateTestFiles({ ...options, write: true });
// after
await migrateTestFiles({ ...options, write: true, overwrite: true }); Defensive patterns
Strategy: validation
Validate before calling
import { lstat, access } from 'node:fs/promises';
async function outputsMissing(plan: { files: { outputPath: string }[] }): Promise<boolean> {
for (const f of plan.files) {
try { await access(f.outputPath); return false; } catch { /* missing is good */ }
}
return true;
}
// then: if (await outputsMissing(plan) || wantOverwrite) await applyMigrationPlan(plan, { overwrite: true }); Try / catch
try {
await migrateTestFiles({ ...options, write: true });
} catch (e) {
if (e instanceof Error && e.message.includes('enable overwrite explicitly')) {
await migrateTestFiles({ ...options, write: true, overwrite: true });
} else throw e;
} Prevention
- Pass overwrite:true when re-running migrations intentionally
- Or write to a fresh temp outputRoot per run to sidestep collisions
When it happens
Trigger: Calling applyMigrationPlan (or migrateTestFiles with write:true) without overwrite when the output file already exists — typically when re-running a migration that already wrote its outputs.
Common situations: Re-running a migration after a partial failure or after inspecting the first run's output; running the same command twice in CI without a clean output directory.
Related errors
- Refusing to overwrite a symbolic link: ${outputPath}
- Output path is not a regular file: ${outputPath}
- Duplicate output path: ${outputLocalName}
- Output path must identify a file below outputRoot: ${outputP
- Duplicate output path: ${outputPath}
AI-assisted analysis of ReactiveX/rxjs@54796b38a5 (2026-08-28).
Data as JSON: /api/errors/756eaa98d94f03e4.
Report an issue: GitHub.