{"record":{"id":"f0be2dd51a29442c","repo":"ReactiveX/rxjs","slug":"an-output-path-ancestor-is-not-a-directory-exis","errorCode":null,"errorMessage":"An output path ancestor is not a directory: ${existing}","messagePattern":"An output path ancestor is not a directory: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/migrate/src/node.ts","lineNumber":230,"sourceCode":" */\nasync function canonicalFuturePath(path: string): Promise<string> {\n  const missing: string[] = [];\n  let existing = path;\n  let canonicalExisting: string | undefined;\n  while (canonicalExisting === undefined) {\n    try {\n      canonicalExisting = await realpath(existing);\n    } catch (error: unknown) {\n      if (!isMissingPathError(error)) throw error;\n      const parent = dirname(existing);\n      if (parent === existing) throw error;\n      missing.push(basename(existing));\n      existing = parent;\n    }\n  }\n  if (missing.length > 0) {\n    const existingStats = await stat(canonicalExisting);\n    if (!existingStats.isDirectory()) throw new Error(`An output path ancestor is not a directory: ${existing}`);\n  }\n  return resolve(canonicalExisting, ...missing.reverse());\n}\n\nfunction isMissingPathError(error: unknown): error is NodeJS.ErrnoException {\n  return error instanceof Error && 'code' in error && error.code === 'ENOENT';\n}\n","sourceCodeStart":212,"sourceCodeEnd":238,"githubUrl":"https://github.com/ReactiveX/rxjs/blob/54796b38a57e6309f9861e174737479bb3f63f61/packages/migrate/src/node.ts#L212-L238","documentation":"Thrown by canonicalFuturePath when an output path has missing trailing components (to be created) but the nearest existing ancestor on disk is not a directory, so the missing children could never be created. It protects output paths like dist/gen/ where 'dist' exists as a file.","triggerScenarios":"Calling canonicalOutputPath (or skill-install's canonicalFuturePath) with a path such as 'dist/a/b' where 'dist' exists as a regular file, so walking up finds a non-directory ancestor.","commonSituations":"Output directories nested under a path occupied by a file from an earlier build, git artifacts, or editor swap files blocking directory creation.","solutions":["Remove the file blocking the ancestor directory (rm <file>)","Use an output path whose existing ancestors are all directories","Pick a fresh output directory name"],"exampleFix":"# before\nplan --output dist/gen  # dist is a file\n# after\nrm dist && mkdir -p dist && plan --output dist/gen","handlingStrategy":"validation","validationCode":"import { stat } from 'node:fs/promises';\nlet cur = path.dirname(outPath);\nwhile (true) {\n  try { if (!(await stat(cur)).isDirectory()) throw new Error(`ancestor not a directory: ${cur}`); break; } catch (e) { if ((e as NodeJS.ErrnoException).code !== 'ENOENT') throw e; cur = path.dirname(cur); if (cur === path.dirname(cur)) break; }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run mkdir -p on the output root before migrating","Avoid output paths that reuse names of existing files"],"tags":["filesystem","output-path","validation"],"backgroundTag":"ancestor-not-a-directory","analyzedSha":"54796b38a57e6309f9861e174737479bb3f63f61","analyzedAt":"2026-08-28T10:21:27.410Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}