{"record":{"id":"7f2ed8a52ac2a6ee","repo":"Yeachan-Heo/oh-my-codex","slug":"catalog-manifest-invalid-agents-index-category","errorCode":null,"errorMessage":"catalog_manifest_invalid:agents[${index}].category","messagePattern":"catalog_manifest_invalid:agents\\[(.+?)\\]\\.category","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/catalog/schema.ts","lineNumber":99,"sourceCode":"    return {\n      name,\n      category: entry.category as CatalogSkillCategory,\n      status: entry.status as CatalogEntryStatus,\n      canonical,\n      core: entry.core === true,\n      internalRequired: entry.internalRequired === true,\n    };\n  });\n\n  const seenAgents = new Set<string>();\n  const agents: CatalogAgentEntry[] = input.agents.map((entry, index) => {\n    if (!isObject(entry)) throw new Error(`catalog_manifest_invalid:agents[${index}]`);\n    assertNonEmptyString(entry.name, `agents[${index}].name`);\n    assertNonEmptyString(entry.category, `agents[${index}].category`);\n    assertNonEmptyString(entry.status, `agents[${index}].status`);\n\n    if (!AGENT_CATEGORIES.has(entry.category as CatalogAgentCategory)) {\n      throw new Error(`catalog_manifest_invalid:agents[${index}].category`);\n    }\n    if (!ENTRY_STATUSES.has(entry.status as CatalogEntryStatus)) {\n      throw new Error(`catalog_manifest_invalid:agents[${index}].status`);\n    }\n\n    const name = entry.name.trim();\n    if (seenAgents.has(name)) throw new Error(`catalog_manifest_invalid:duplicate_agent:${name}`);\n    seenAgents.add(name);\n\n    const canonical = typeof entry.canonical === 'string' && entry.canonical.trim() !== ''\n      ? entry.canonical.trim()\n      : undefined;\n\n    if ((entry.status === 'alias' || entry.status === 'merged') && !canonical) {\n      throw new Error(`catalog_manifest_invalid:agents[${index}].canonical`);\n    }\n\n    return {","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/catalog/schema.ts#L81-L117","documentation":"agents[i].category must be one of the allowed agent categories: build|review|domain|product|coordination. This error fires when the string is present but not in that set (typos, casing, or new categories from another schema version).","triggerScenarios":"An agent entry with \"category\": \"coding\" or \"Build\" instead of the exact lowercase allowed values.","commonSituations":"Hand-edited manifests, or manifests generated by a newer catalog schema that introduced new categories.","solutions":["Set category to one of build, review, domain, product, coordination (exact lowercase)","Check CatalogAgentCategory in the installed version for the authoritative list","Regenerate the manifest with matching tooling"],"exampleFix":"// before\n{ \"name\": \"builder\", \"category\": \"Build\", \"status\": \"active\" }\n\n// after\n{ \"name\": \"builder\", \"category\": \"build\", \"status\": \"active\" }","handlingStrategy":"validation","validationCode":"const AGENT_CATEGORIES = new Set(['build','review','domain','product','coordination']);\nif (!raw.agents.every((a: any) => AGENT_CATEGORIES.has(a?.category))) { /* fix categories */ }","typeGuard":"function isAgentCategory(v: unknown): v is 'build'|'review'|'domain'|'product'|'coordination' {\n  return typeof v === 'string' && ['build','review','domain','product','coordination'].includes(v);\n}","tryCatchPattern":null,"preventionTips":["Use exact lowercase agent categories","Re-check allowed values after upgrading the library"],"tags":["catalog","manifest","enum","validation","agents"],"backgroundTag":"invalid-enum-value","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}