JuliusBrussee/caveman · error

target already exists: ${path}

Error message

target already exists: ${path}

What it means

Before scaffolding, assertAbsent stats the resolved target path and requires ENOENT — the create initializer must never overwrite an existing directory or file. Any existing filesystem entry (directory, file, symlink) produces this error. This is intentional clobber protection, and it also fires for things like an auto-created editor/IDE folder.

Source

Thrown at packages/create-caveman-agent/src/index.ts:314

  return "GEMINI_API_KEY (or GOOGLE_API_KEY)";
}

function parseProvider(value: string): Provider {
  const normalized = value.trim().toLowerCase();
  if (normalized === "anthropic" || normalized === "openai" || normalized === "google") return normalized;
  throw new Error(`unsupported provider ${JSON.stringify(value)}`);
}

function safeName(value: string): string {
  const normalized = value.toLowerCase().replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
  if (!normalized) throw new Error("project name must contain a letter or number");
  return normalized.slice(0, 96);
}

async function assertAbsent(path: string): Promise<void> {
  try {
    await stat(path);
    throw new Error(`target already exists: ${path}`);
  } catch (error) {
    if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
  }
}

main().catch((error) => {
  const message = error instanceof Error ? error.message : String(error);
  process.stderr.write(`create-caveman-agent: ${message}\n`);
  process.exitCode = 1;
});

View on GitHub (pinned to 27d5a3981a)

Solutions

  1. Pick a fresh target name, or move/remove the existing path if its contents are disposable.
  2. If the existing directory is empty, remove it first (`rmdir myapp`) and re-run.
  3. For resuming a failed attempt, delete the partial scaffold before re-creating.

Example fix

# before
mkdir myapp && npm create @caveman-ai/agent@latest myapp
# after
rmdir myapp && npm create @caveman-ai/agent@latest myapp
Defensive patterns

Strategy: validation

Validate before calling

import { stat } from "node:fs/promises";

async function targetIsFree(path: string): Promise<boolean> {
  try { await stat(path); return false; } catch { return true; }
}

Prevention

When it happens

Trigger: Running the initializer twice with the same target, scaffolding into a directory that already exists (even an empty one created by mkdir beforehand), or targeting a path occupied by a file/symlink.

Common situations: Re-running after a partial previous attempt, users pre-creating the folder, IDE auto-creating the directory when it is opened, or leftover artifacts from an aborted run.

Related errors


AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15). Data as JSON: /api/errors/6e98a0dd2d0453ee. Report an issue: GitHub.