vercel-labs/agent-skills · warning · Error

output file already exists: ${path}. Use a fresh run directo

Error message

output file already exists: ${path}. Use a fresh run directory or pass --force to overwrite.

What it means

Thrown by writeOutput() in merge-signals.mjs when the destination path already exists and `--force` was not passed. The guard (exists() check before writeFile) prevents clobbering a previous merged result, since merges are meant to land in a fresh run directory per the skill's doctrine of reproducible artifacts.

Source

Thrown at skills/vercel-optimize/scripts/merge-signals.mjs:172

}

async function readJson(path, label) {
  try {
    return JSON.parse(await readFile(path, 'utf-8'));
  } catch (err) {
    throw new Error(`Could not read ${label} JSON at ${path}: ${err.message}`);
  }
}

function assertObject(value, label) {
  if (!value || typeof value !== 'object' || Array.isArray(value)) {
    throw new Error(`${label} must be a JSON object.`);
  }
}

async function writeOutput(path, body, { force }) {
  if (!force && await exists(path)) {
    throw new Error(`output file already exists: ${path}. Use a fresh run directory or pass --force to overwrite.`);
  }
  await mkdir(dirname(path), { recursive: true });
  await writeFile(path, body);
}

async function exists(path) {
  try {
    await access(path);
    return true;
  } catch {
    return false;
  }
}

if (process.argv[1] && realpathSync(process.argv[1]) === realpathSync(fileURLToPath(import.meta.url))) {
  main().catch((err) => {
    console.error('[merge-signals] FAILED:', err.message);
    process.exit(1);

View on GitHub (pinned to b8caa260a4)

Solutions

  1. Pass `--force` to overwrite deliberately: `merge-signals.mjs signals.json codebase.json -o out.json --force`.
  2. Write to a fresh run directory each invocation (recommended by the skill).
  3. Delete or rename the stale output before re-running.

Example fix

# before
$ node scripts/merge-signals.mjs s.json c.json -o run1/merged.json
-> output file already exists: run1/merged.json

# after
$ node scripts/merge-signals.mjs s.json c.json -o run2/merged.json
# or
$ node scripts/merge-signals.mjs s.json c.json -o run1/merged.json --force
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
function assertOutputWritable(path, force) {
  if (existsSync(path) && !force) {
    throw new Error(`${path} exists; pass --force or use a fresh run directory`);
  }
}
assertOutputWritable(outPath, args.force);

Try / catch

try {
  await writeOutput(outPath, body, { force });
} catch (err) {
  if (err.message.startsWith('output file already exists')) {
    // either pass --force or pick a new path, then retry
  }
  throw err;
}

Prevention

When it happens

Trigger: Re-running merge-signals into the same output path from a prior run without `--force`; an output directory reused across runs; a typo pointing -o at an existing file.

Common situations: Iterating on a merge and forgetting to change the output name; CI reusing a workspace without cleaning; a run directory shared between merge and prepare-brief steps.

Related errors


AI-assisted analysis of vercel-labs/agent-skills@b8caa260a4 (2026-08-13). Data as JSON: /api/errors/2f39645e6cbf5fb9. Report an issue: GitHub.