yamadashy/repomix · error · RepomixError

Skill directory already exists: ${skillDir}. Use --force to

Error message

Skill directory already exists: ${skillDir}. Use --force to overwrite.

What it means

Also in prepareSkillDir (non-interactive skill generation): if the target path exists and IS a directory but `force` is false, Repomix refuses to overwrite and throws this error telling you to use --force. Only an ENOENT (path does not exist) is treated as success; any other error — including this one — propagates. This protects existing skill content from being silently rm -rf'd by regeneration.

Source

Thrown at src/cli/prompts/skillPrompts.ts:130

  force: boolean,
  deps = {
    access: fs.access,
    rm: fs.rm,
    stat: fs.stat,
  },
): Promise<void> => {
  try {
    await deps.access(skillDir);
    // Path exists - check if it's a directory
    const stats = await deps.stat(skillDir);
    if (!stats.isDirectory()) {
      throw new RepomixError(`Skill output path exists but is not a directory: ${skillDir}`);
    }
    // Directory exists
    if (force) {
      await deps.rm(skillDir, { recursive: true, force: true });
    } else {
      throw new RepomixError(`Skill directory already exists: ${skillDir}. Use --force to overwrite.`);
    }
  } catch (error) {
    // Re-throw if it's not a "file not found" error
    if ((error as NodeJS.ErrnoException)?.code !== 'ENOENT') {
      throw error;
    }
    // Directory doesn't exist - good to go
  }
};

/**
 * Resolve skill output path and prepare directory for non-interactive mode.
 * Returns the resolved skill directory path.
 */
export const resolveAndPrepareSkillDir = async (skillOutput: string, cwd: string, force: boolean): Promise<string> => {
  const skillDir = path.isAbsolute(skillOutput) ? skillOutput : path.resolve(cwd, skillOutput);
  await prepareSkillDir(skillDir, force);
  return skillDir;

View on GitHub (pinned to f465ad9093)

Solutions

  1. Re-run with `--force` to delete the existing skill directory and regenerate it (confirm the contents are disposable first).
  2. Delete or move the existing directory manually, then re-run without --force.
  3. Choose a different output path/skill name if you want to keep both versions.
  4. In scripts, gate on existence first if you need to avoid ever passing --force blindly.

Example fix

# before
repomix --skill --output .claude/skills/my-skill
# Error: Skill directory already exists...

# after
repomix --skill --output .claude/skills/my-skill --force
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs/promises';
let exists = false;
try { await fs.access(skillDir); exists = true; } catch {}
if (exists && !force) {
  console.error(`${skillDir} already exists; pass --force to overwrite.`);
  process.exit(1);
}

Try / catch

try {
  await resolveAndPrepareSkillDir(skillOutput, cwd, force);
} catch (e) {
  if (e instanceof RepomixError && e.message.includes('Skill directory already exists')) {
    console.error('Re-run with --force or remove the directory first.');
  } else throw e;
}

Prevention

When it happens

Trigger: Running skill generation non-interactively with an output path whose directory already exists (from a previous generation or manual creation) without passing --force. resolveAndPrepareSkillDir -> prepareSkillDir detects access()+isDirectory() and force=false.

Common situations: Re-running skill generation for a skill you generated before; CI reruns without force; directory pre-created by scaffolding tools or a repo checkout.

Related errors


AI-assisted analysis of yamadashy/repomix@f465ad9093 (2026-08-29). Data as JSON: /api/errors/fb8cb94854d934a8. Report an issue: GitHub.