{"record":{"id":"756eaa98d94f03e4","repo":"ReactiveX/rxjs","slug":"output-path-already-exists-enable-overwrite-expli","errorCode":null,"errorMessage":"Output path already exists; enable overwrite explicitly: ${outputPath}","messagePattern":"Output path already exists; enable overwrite explicitly: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/migrate/src/node.ts","lineNumber":160,"sourceCode":"  for (const { sourcePath, outputPath, result } of plan.files) {\n    if (result.status === 'refused') throw new Error(`Migration result was refused for source: ${sourcePath}`);\n    const resolvedOutputPath = resolve(outputPath);\n    if (resolvedOutputPath === outputRoot) throw new Error(`Output path must identify a file below outputRoot: ${outputPath}`);\n    assertContained(outputRoot, resolvedOutputPath, `Output path is outside outputRoot: ${outputPath}`);\n    const canonicalOutputPath = await canonicalFuturePath(resolvedOutputPath);\n    assertContained(canonicalOutputRoot, canonicalOutputPath, `Output path resolves outside outputRoot: ${outputPath}`);\n    if (canonicalOutputs.has(canonicalOutputPath)) throw new Error(`Duplicate output path: ${outputPath}`);\n    canonicalOutputs.add(canonicalOutputPath);\n    await assertWritableOutput(resolvedOutputPath, options.overwrite ?? false);\n  }\n}\n\nasync function assertWritableOutput(outputPath: string, overwrite: boolean): Promise<void> {\n  try {\n    const outputStats = await lstat(outputPath);\n    if (outputStats.isSymbolicLink()) throw new Error(`Refusing to overwrite a symbolic link: ${outputPath}`);\n    if (!outputStats.isFile()) throw new Error(`Output path is not a regular file: ${outputPath}`);\n    if (!overwrite) throw new Error(`Output path already exists; enable overwrite explicitly: ${outputPath}`);\n  } catch (error: unknown) {\n    if (!isMissingPathError(error)) throw error;\n  }\n}\n\nexport async function migrateTestFiles(options: MigrateFilesOptions): Promise<readonly MigratedFile[]> {\n  if (options.write && !options.outputRoot) {\n    throw new Error('outputRoot is required when write is enabled.');\n  }\n  const plan = await planMigrationFiles(options);\n  return options.write ? applyMigrationPlan(plan, { overwrite: options.overwrite }) : plan.files;\n}\n\nfunction safeOutputPath(outputRoot: string, outputName: string): string {\n  if (!outputName || outputName === '.' || isAbsolute(outputName)) {\n    throw new Error(`Output name must be a non-empty relative path: ${outputName || '<empty>'}`);\n  }\n  const outputPath = resolve(outputRoot, outputName);","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/ReactiveX/rxjs/blob/54796b38a57e6309f9861e174737479bb3f63f61/packages/migrate/src/node.ts#L142-L178","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait migrateTestFiles({ ...options, write: true });\n\n// after\nawait migrateTestFiles({ ...options, write: true, overwrite: true });","handlingStrategy":"validation","validationCode":"import { lstat, access } from 'node:fs/promises';\nasync function outputsMissing(plan: { files: { outputPath: string }[] }): Promise<boolean> {\n  for (const f of plan.files) {\n    try { await access(f.outputPath); return false; } catch { /* missing is good */ }\n  }\n  return true;\n}\n// then: if (await outputsMissing(plan) || wantOverwrite) await applyMigrationPlan(plan, { overwrite: true });","typeGuard":null,"tryCatchPattern":"try {\n  await migrateTestFiles({ ...options, write: true });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('enable overwrite explicitly')) {\n    await migrateTestFiles({ ...options, write: true, overwrite: true });\n  } else throw e;\n}","preventionTips":["Pass overwrite:true when re-running migrations intentionally","Or write to a fresh temp outputRoot per run to sidestep collisions"],"tags":["migrate","filesystem","overwrite","write-safety"],"backgroundTag":"refusing-file-overwrite","analyzedSha":"54796b38a57e6309f9861e174737479bb3f63f61","analyzedAt":"2026-08-28T10:21:27.410Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}