ReactiveX/rxjs · error · Error

An output path ancestor is not a directory: ${existing}

Error message

An output path ancestor is not a directory: ${existing}

What it means

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.

Source

Thrown at packages/migrate/src/node.ts:230

 */
async function canonicalFuturePath(path: string): Promise<string> {
  const missing: string[] = [];
  let existing = path;
  let canonicalExisting: string | undefined;
  while (canonicalExisting === undefined) {
    try {
      canonicalExisting = await realpath(existing);
    } catch (error: unknown) {
      if (!isMissingPathError(error)) throw error;
      const parent = dirname(existing);
      if (parent === existing) throw error;
      missing.push(basename(existing));
      existing = parent;
    }
  }
  if (missing.length > 0) {
    const existingStats = await stat(canonicalExisting);
    if (!existingStats.isDirectory()) throw new Error(`An output path ancestor is not a directory: ${existing}`);
  }
  return resolve(canonicalExisting, ...missing.reverse());
}

function isMissingPathError(error: unknown): error is NodeJS.ErrnoException {
  return error instanceof Error && 'code' in error && error.code === 'ENOENT';
}

View on GitHub (pinned to 54796b38a5)

Solutions

  1. Remove the file blocking the ancestor directory (rm <file>)
  2. Use an output path whose existing ancestors are all directories
  3. Pick a fresh output directory name

Example fix

# before
plan --output dist/gen  # dist is a file
# after
rm dist && mkdir -p dist && plan --output dist/gen
Defensive patterns

Strategy: validation

Validate before calling

import { stat } from 'node:fs/promises';
let cur = path.dirname(outPath);
while (true) {
  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; }
}

Prevention

When it happens

Trigger: 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.

Common situations: Output directories nested under a path occupied by a file from an earlier build, git artifacts, or editor swap files blocking directory creation.

Related errors


AI-assisted analysis of ReactiveX/rxjs@54796b38a5 (2026-08-28). Data as JSON: /api/errors/f0be2dd51a29442c. Report an issue: GitHub.