Yeachan-Heo/oh-my-codex · error · Error
catalog_manifest_invalid:duplicate_agent:${name}
Error message
catalog_manifest_invalid:duplicate_agent:${name} What it means
Agent names must be unique after trimming; when the same trimmed name appears twice in agents, the validator throws catalog_manifest_invalid:duplicate_agent:<name> with the duplicate name embedded. This prevents ambiguous agent resolution.
Source
Thrown at src/catalog/schema.ts:106
};
});
const seenAgents = new Set<string>();
const agents: CatalogAgentEntry[] = input.agents.map((entry, index) => {
if (!isObject(entry)) throw new Error(`catalog_manifest_invalid:agents[${index}]`);
assertNonEmptyString(entry.name, `agents[${index}].name`);
assertNonEmptyString(entry.category, `agents[${index}].category`);
assertNonEmptyString(entry.status, `agents[${index}].status`);
if (!AGENT_CATEGORIES.has(entry.category as CatalogAgentCategory)) {
throw new Error(`catalog_manifest_invalid:agents[${index}].category`);
}
if (!ENTRY_STATUSES.has(entry.status as CatalogEntryStatus)) {
throw new Error(`catalog_manifest_invalid:agents[${index}].status`);
}
const name = entry.name.trim();
if (seenAgents.has(name)) throw new Error(`catalog_manifest_invalid:duplicate_agent:${name}`);
seenAgents.add(name);
const canonical = typeof entry.canonical === 'string' && entry.canonical.trim() !== ''
? entry.canonical.trim()
: undefined;
if ((entry.status === 'alias' || entry.status === 'merged') && !canonical) {
throw new Error(`catalog_manifest_invalid:agents[${index}].canonical`);
}
return {
name,
category: entry.category as CatalogAgentCategory,
status: entry.status as CatalogEntryStatus,
canonical,
};
});
View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Locate both entries with the name in the message and remove or rename one
- Represent the extra as a distinct alias name with canonical pointing at the primary
- Deduplicate the source data and regenerate
Example fix
// before
"agents": [ {"name":"builder",...}, {"name":"builder",...} ]
// after
"agents": [ {"name":"builder",...}, {"name":"build-agent","status":"alias","canonical":"builder","category":"build"} ] Defensive patterns
Strategy: validation
Validate before calling
const names = raw.agents.map((a: any) => String(a.name).trim());
if (new Set(names).size !== names.length) { /* dedupe before validation */ } Prevention
- Dedupe agent lists when merging manifests
- Use alias entries with distinct names and canonical
When it happens
Trigger: Two agent entries with the same name (whitespace differences count as equal since comparison is on trimmed names).
Common situations: Concatenating manifests from multiple teams/sources, or duplicates introduced during category reorganization.
Related errors
- catalog_manifest_invalid:duplicate_skill:${name}
- catalog_manifest_invalid:agents[${index}]
- catalog_manifest_invalid:agents[${index}].category
- catalog_manifest_invalid:agents[${index}].status
- catalog_manifest_invalid:agents[${index}].canonical
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/a7c967d6e5f0b9c5.
Report an issue: GitHub.