Yeachan-Heo/oh-my-codex · error · Error

catalog_manifest_invalid:agents[${index}].category

Error message

catalog_manifest_invalid:agents[${index}].category

What it means

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).

Source

Thrown at src/catalog/schema.ts:99

    return {
      name,
      category: entry.category as CatalogSkillCategory,
      status: entry.status as CatalogEntryStatus,
      canonical,
      core: entry.core === true,
      internalRequired: entry.internalRequired === true,
    };
  });

  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 {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Set category to one of build, review, domain, product, coordination (exact lowercase)
  2. Check CatalogAgentCategory in the installed version for the authoritative list
  3. Regenerate the manifest with matching tooling

Example fix

// before
{ "name": "builder", "category": "Build", "status": "active" }

// after
{ "name": "builder", "category": "build", "status": "active" }
Defensive patterns

Strategy: validation

Validate before calling

const AGENT_CATEGORIES = new Set(['build','review','domain','product','coordination']);
if (!raw.agents.every((a: any) => AGENT_CATEGORIES.has(a?.category))) { /* fix categories */ }

Type guard

function isAgentCategory(v: unknown): v is 'build'|'review'|'domain'|'product'|'coordination' {
  return typeof v === 'string' && ['build','review','domain','product','coordination'].includes(v);
}

Prevention

When it happens

Trigger: An agent entry with "category": "coding" or "Build" instead of the exact lowercase allowed values.

Common situations: Hand-edited manifests, or manifests generated by a newer catalog schema that introduced new categories.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/7f2ed8a52ac2a6ee. Report an issue: GitHub.