paperclipai/paperclip · error · Error

Output path already exists and is not a directory: ${outputD

Error message

Output path already exists and is not a directory: ${outputDir}

What it means

ensureEmptyOutputDirectory stats the target path; if it exists and is not a directory (i.e., a file or symlink to a file), it refuses to proceed to avoid clobbering.

Source

Thrown at cli/src/commands/client/feedback.ts:559

function horizontalRule(): string {
  return pc.dim("-".repeat(72));
}

function padRight(value: string, width: number): string {
  return `${value}${" ".repeat(Math.max(0, width - value.length))}`;
}

function defaultFeedbackExportDirName(): string {
  const iso = new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
  return `feedback-export-${iso}`;
}

async function ensureEmptyOutputDirectory(outputDir: string): Promise<void> {
  try {
    const info = await stat(outputDir);
    if (!info.isDirectory()) {
      throw new Error(`Output path already exists and is not a directory: ${outputDir}`);
    }
    const entries = await readdir(outputDir);
    if (entries.length > 0) {
      throw new Error(`Output directory already exists and is not empty: ${outputDir}`);
    }
  } catch (error) {
    const message = error instanceof Error ? error.message : "";
    if (/ENOENT/.test(message)) {
      await mkdir(outputDir, { recursive: true });
      return;
    }
    throw error;
  }
}

async function collectJsonFilesForArchive(
  outputDir: string,
  relativePaths: string[],

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Remove or rename the existing file at that path.
  2. Point --output at a fresh directory path.
  3. Omit --output to let the CLI generate a timestamped feedback-export-<iso> directory.

Example fix

// before
paperclipai feedback trace export --output ./out.zip
// after
rm ./out.zip && paperclipai feedback trace export --output ./out.zip
Defensive patterns

Strategy: validation

Validate before calling

import {stat} from 'node:fs/promises';
try {
  const info = await stat(outputDir);
  if (!info.isDirectory()) throw new Error(`Output path already exists and is not a directory: ${outputDir}`);
} catch (e) { /* ENOENT is fine */ }

Prevention

When it happens

Trigger: Passing --output <path> where <path> is an existing regular file.

Common situations: Reusing a name that a previous run or another tool created as a file; --output pointing at an archive file.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/f1934b6f91854f3a. Report an issue: GitHub.