{"record":{"id":"d742995cfacde716","repo":"paperclipai/paperclip","slug":"ambiguous-skill-slug-trimmed-use-a-skill-id","errorCode":null,"errorMessage":"Ambiguous skill slug \"${trimmed}\". Use a skill ID or key instead.","messagePattern":"Ambiguous skill slug \"(.+?)\"\\. Use a skill ID or key instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"cli/src/commands/client/skills.ts","lineNumber":624,"sourceCode":"  skills: CompanySkillReferenceTarget[],\n  reference: string,\n): CompanySkillReferenceTarget {\n  const trimmed = reference.trim();\n  if (!trimmed) {\n    throw new Error(\"Skill reference is required.\");\n  }\n\n  const byId = skills.find((skill) => skill.id === trimmed);\n  if (byId) return byId;\n\n  const byKey = skills.find((skill) => skill.key === trimmed);\n  if (byKey) return byKey;\n\n  const normalizedSlug = normalizeSkillSlug(trimmed);\n  const bySlug = skills.filter((skill) => skill.slug === normalizedSlug);\n  if (bySlug.length === 1 && bySlug[0]) return bySlug[0];\n  if (bySlug.length > 1) {\n    throw new Error(`Ambiguous skill slug \"${trimmed}\". Use a skill ID or key instead.`);\n  }\n\n  throw new Error(`Skill not found: ${reference}`);\n}\n\nasync function resolveCompanySkill(\n  ctx: ResolvedClientContext,\n  reference: string,\n): Promise<CompanySkillReferenceTarget> {\n  return resolveCompanySkillReference(await listCompanySkills(ctx), reference);\n}\n\nasync function checkCompanySkills(\n  ctx: ResolvedClientContext,\n  skillRef: string | undefined,\n): Promise<CompanySkillCheckRow[]> {\n  const skills = await listCompanySkills(ctx);\n  const selected = skillRef ? [resolveCompanySkillReference(skills, skillRef)] : skills;","sourceCodeStart":606,"sourceCodeEnd":642,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/cli/src/commands/client/skills.ts#L606-L642","documentation":"Thrown by resolveCompanySkillReference() when the trimmed reference matches no skill by id or key, but normalizes to a slug that two or more installed company skills share. The resolver refuses to guess; it requires an unambiguous id or key instead. Slug normalization lowercases and collapses non-alphanumerics to hyphens.","triggerScenarios":"Two installed skills end up with the same normalized slug (e.g. one named \"My Skill\" and another imported as \"my-skill\"), and the user addresses them by that slug: `paperclipai skills show my-skill`.","commonSituations":"Importing a catalog skill with a custom --as slug that collides with an existing skill, or two catalog skills whose display names normalize identically. More likely after merges or cross-company imports.","solutions":["Use the unique skill id from `skills list` (the `id` column) instead of the slug.","Alternatively use the skill `key` shown in the list output.","Long-term: rename or remove one of the colliding skills so slugs become unique."],"exampleFix":"// before\nawait run([\"skills\", \"show\", \"my-skill\"]);\n// after\nconst rows = await runJson([\"skills\", \"list\", \"--json\"]);\nconst match = rows.find(r => r.slug === \"my-skill\");\nawait run([\"skills\", \"show\", match.id]);  // unambiguous","handlingStrategy":"validation","validationCode":"const skills = await runJson([\"skills\", \"list\", \"--json\"]);\nconst slug = normalizeSlug(ref);\nconst matches = skills.filter(s => s.slug === slug);\nif (matches.length > 1) {\n  throw new Error(`Ambiguous slug; use one of: ${matches.map(m => m.id).join(\", \")}`);\n}\n// safe to use slug\nfunction normalizeSlug(v: string) {\n  return v.trim().toLowerCase().replace(/[^a-z0-9]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n}","typeGuard":"function isUnambiguousSkill(skills: Array<{slug: string}>, slug: string): boolean {\n  return skills.filter(s => s.slug === slug).length === 1;\n}","tryCatchPattern":null,"preventionTips":["Prefer the id from `skills list` over hand-typed slugs.","Detect collisions up front by counting slug matches.","Rename colliding skills so slugs become unique."],"tags":["cli","ambiguous","skills","slug","resolution"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}