vercel/ai · error · Error
Duplicate skill name: ${skills[index]!.name}
Error message
Duplicate skill name: ${skills[index]!.name} What it means
Thrown by assertUniqueSkillNames in packages/harness/src/utils/write-skills.ts when two or more skills passed to writeSkills project to the same name. Duplicate directory names cannot be written to the same rootDir, so the harness rejects the input before touching the filesystem. The skills array is sorted by name first, so duplicates are detected by adjacent comparison.
Source
Thrown at packages/harness/src/utils/write-skills.ts:457
errorMessage,
}: {
sandbox: Experimental_SandboxSession;
command: string;
abortSignal?: AbortSignal;
errorMessage: string;
}): Promise<void> {
const result = await sandbox.run({ command, abortSignal });
if (result.exitCode !== 0) {
throw new Error(
`${errorMessage} (exit ${result.exitCode})${result.stderr ? `: ${result.stderr}` : ''}`,
);
}
}
function assertUniqueSkillNames(skills: ReadonlyArray<ProjectedSkill>): void {
for (let index = 1; index < skills.length; index++) {
if (skills[index - 1]!.name === skills[index]!.name) {
throw new Error(`Duplicate skill name: ${skills[index]!.name}`);
}
}
}
function isSafeManifestSkillName(name: string): boolean {
SAFE_MANIFEST_SKILL_NAME.lastIndex = 0;
const matches = SAFE_MANIFEST_SKILL_NAME.test(name);
SAFE_MANIFEST_SKILL_NAME.lastIndex = 0;
return matches && name !== '.' && name !== '..' && !name.includes('/');
}
function validateSkillName({
name,
pattern,
message,
}: {
name: string;
pattern: RegExp;View on GitHub (pinned to 69428b1f8b)
Solutions
- Deduplicate the skills array by name before calling writeSkills (e.g. with a Map keyed by name).
- Rename one of the conflicting skills so names are unique.
- Log the full skill name list to find which entries collide.
- Guard the input at construction time so duplicate names never reach writeSkills.
Example fix
// before
await writeSkills({ sandbox, rootDir, skills: [skillA, skillA] });
// after
const unique = [...new Map(skills.map(s => [s.name, s])).values()];
await writeSkills({ sandbox, rootDir, skills: unique }); Defensive patterns
Strategy: validation
Validate before calling
const names = skills.map(s => s.name);
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
if (dupes.length) throw new Error(`Duplicate skill names: ${[...new Set(dupes)].join(', ')}`); Try / catch
try {
await writeSkills({ sandbox, rootDir, skills });
} catch (error) {
if (/Duplicate skill name:/.test((error as Error).message)) {
const unique = [...new Map(skills.map(s => [s.name, s])).values()];
await writeSkills({ sandbox, rootDir, skills: unique });
} else throw error;
} Prevention
- Deduplicate skills by name at collection time (Map/Set by name).
- Enforce unique names where skills are defined, not at the writeSkills boundary.
- When merging skill lists from multiple sources, log dropped duplicates.
- Add a unit test asserting skill name uniqueness in your skill registry.
When it happens
Trigger: Calling writeSkills with a skills array containing two HarnessV1Skill entries whose `name` values are identical (after projection/naming), e.g. the same skill object passed twice or two skills generated from overlapping sources.
Common situations: Programmatic skill collection that merges lists without deduplicating; skills loaded from multiple directories with identical folder names; passing the same skill definition under two providers/configs.
Related errors
- maxInputBytesPerCall must be greater than 0
- No object generated: the model did not return a response.
- Invalid skill name: ${name}
- maxEmbeddingsPerCall must be greater than 0
- No image generated.
AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30).
Data as JSON: /api/errors/fbed497d52b4bee9.
Report an issue: GitHub.