vercel/ai · error · Error

Cannot write harness skill '${skillName}': ${skillDir} alrea

Error message

Cannot write harness skill '${skillName}': ${skillDir} already exists and is not owned by the AI SDK harness.

What it means

Thrown by assertSkillDirectoryAvailable in packages/harness/src/utils/write-skills.ts when the target skill directory (<rootDir>/<skillName>) already exists in the sandbox and is not recorded as harness-owned in the skills manifest. The harness refuses to overwrite directories it did not create to avoid destroying user-managed content. The `test ! -e <dir>` probe returning non-zero means the path exists.

Source

Thrown at packages/harness/src/utils/write-skills.ts:382

async function assertSkillDirectoryAvailable({
  sandbox,
  rootDir,
  skillName,
  abortSignal,
}: {
  sandbox: Experimental_SandboxSession;
  rootDir: string;
  skillName: string;
  abortSignal?: AbortSignal;
}): Promise<void> {
  const skillDir = path.posix.join(rootDir, skillName);
  const result = await sandbox.run({
    command: `test ! -e ${shellQuote(skillDir)}`,
    abortSignal,
  });
  if (result.exitCode !== 0) {
    throw new Error(
      `Cannot write harness skill '${skillName}': ${skillDir} already exists and is not owned by the AI SDK harness.`,
    );
  }
}

async function removeSkillDirectories({
  sandbox,
  rootDir,
  skillNames,
  abortSignal,
}: {
  sandbox: Experimental_SandboxSession;
  rootDir: string;
  skillNames: ReadonlyArray<string>;
  abortSignal?: AbortSignal;
}): Promise<void> {
  if (skillNames.length === 0) return;
  const directories = Array.from(new Set(skillNames))

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Rename your skill to a non-conflicting name, or move/remove the existing directory in rootDir manually.
  2. If the directory is a leftover from a previous harness run, remove it (and align the manifest) before writing.
  3. Point rootDir at a dedicated directory (e.g. /workspace/.claude/skills) rather than a shared folder.
  4. Check what exists at <rootDir>/<skillName> in the sandbox before writing.

Example fix

// before
await writeSkills({ sandbox, rootDir: '/workspace', skills: [{ name: 'docs', files }] }); // /workspace/docs exists, not harness-owned
// after
await writeSkills({ sandbox, rootDir: '/workspace', skills: [{ name: 'api-docs', files }] });
Defensive patterns

Strategy: validation

Validate before calling

for (const skill of skills) {
  const dir = `${rootDir}/${skill.name}`;
  const check = await sandbox.run({ command: `test ! -e ${dir}` });
  if (check.exitCode !== 0) throw new Error(`Path exists, move or rename before writing: ${dir}`);
}

Try / catch

try {
  await writeSkills({ sandbox, rootDir, skills });
} catch (error) {
  if (/already exists and is not owned by the AI SDK harness/.test((error as Error).message)) {
    // surface a user-facing conflict error; do NOT auto-delete foreign directories
    throw new Error(`Conflict: ${skillName} exists in ${rootDir}; remove or rename it first.`);
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling writeSkills with a skill whose name collides with an existing directory in rootDir that is absent from the harness manifest — e.g. a user-created folder, a skill installed by another tool, or a leftover directory whose manifest entry was deleted.

Common situations: Skill name collides with a pre-existing project folder (e.g. 'docs', 'test'); switching skill rootDir so the manifest no longer lists existing directories; a previous manifest was removed but skill dirs remain.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/c8ccf14dafe122f2. Report an issue: GitHub.