vercel/ai · error · Error

Duplicate Cline skill identifier: ${id}

Error message

Duplicate Cline skill identifier: ${id}

What it means

After validating unique skill names, projectClineSkills derives a normalized identifier via normalizeSkillToken(skill.name) and requires ids to be unique too. Two distinct names can normalize to the same token (e.g. 'My Skill' and 'my-skill'), which would create ambiguous skill ids, so it throws.

Source

Thrown at packages/harness-cline/src/cline-skills.ts:105

  const names = new Set<string>();
  const ids = new Set<string>();
  return skills
    .map(skill => {
      if (
        !CLINE_SKILL_NAME_PATTERN.test(skill.name) ||
        skill.name === '.' ||
        skill.name === '..'
      ) {
        throw new Error(`Invalid Cline skill name: ${skill.name}`);
      }
      if (names.has(skill.name)) {
        throw new Error(`Duplicate Cline skill name: ${skill.name}`);
      }
      names.add(skill.name);

      const id = normalizeSkillToken(skill.name);
      if (ids.has(id)) {
        throw new Error(`Duplicate Cline skill identifier: ${id}`);
      }
      ids.add(id);

      return {
        id,
        name: skill.name,
        description: skill.description,
        content: skill.content,
        files: (skill.files ?? [])
          .map(file => ({
            path: normalizeSkillFilePath({
              skillName: skill.name,
              filePath: file.path,
            }),
            content: file.content,
          }))
          .sort(
            (left, right) =>

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Rename one skill so its normalized token differs (change casing, spacing, or punctuation).
  2. Check the colliding id printed in the message and inspect which names map to it.
  3. Pre-normalize skill names (kebab-case) across all skill sources before registering them.

Example fix

// before
skills named 'Code Review' and 'code-review' both registered
// after
// rename one, e.g. 'Code Review' -> 'code-review-strict'
Defensive patterns

Strategy: validation

Validate before calling

const ids = new Set();
for (const s of skills) {
  const id = s.name.toLowerCase().replace(/[^a-z0-9]+/g, '-');
  if (ids.has(id)) throw new Error(`colliding skill id: ${id}`);
  ids.add(id);
}

Try / catch

try {
  await projectedSkills(input);
} catch (e) {
  if (/Duplicate Cline skill identifier/.test(String(e?.message))) {
    // rename skill to avoid token collision, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: projectClineSkills receives skills with distinct names that normalize to the same token, e.g. 'Deploy Helper' and 'deploy-helper' or 'deploy_helper' and 'deploy-helper'.

Common situations: Skills authored in different naming conventions (Title Case vs kebab-case) that collide after token normalization; importing the same skill from two sources under slightly different names.

Related errors


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