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

Invalid agentTypes entries: ${invalid.join(', ')}. Expected

Error message

Invalid agentTypes entries: ${invalid.join(', ')}. Expected codex|claude|gemini.

What it means

normalizeAgentTypes validates the --agentTypes-style array: after trim/lowercase, every entry must be exactly 'codex', 'claude', or 'gemini'. Any other string (including empty strings, provider names with typos like 'claude-code' or 'gpt') makes the invalid list non-empty and throws. The message lists the offending entries.

Source

Thrown at src/team/runtime-cli.ts:218

  workerCount: number,
  startTimeMs: number,
): TerminalCliResult {
  const status = phase === 'complete' ? 'completed' : 'failed';
  return {
    output: buildCliOutput(stateRoot, teamName, status, workerCount, startTimeMs),
    exitCode: status === 'completed' ? 0 : 1,
    notice:
      `[runtime-cli] phase=${phase} reached terminal state; preserving team state for inspection. `
      + `Inspect with "omx team status ${teamName} --json" or "omx team api read-stall-state --input '{\"team_name\":\"${teamName}\"}' --json". `
      + `Run "omx team shutdown ${teamName}" (or --force after state capture) when explicit cleanup is desired.\n`,
  };
}

export function normalizeAgentTypes(raw: string[], workerCount: number): TeamWorkerProvider[] {
  const providers = raw.map((entry) => String(entry || '').trim().toLowerCase());
  const invalid = providers.filter((entry) => entry !== 'codex' && entry !== 'claude' && entry !== 'gemini');
  if (invalid.length > 0) {
    throw new Error(`Invalid agentTypes entries: ${invalid.join(', ')}. Expected codex|claude|gemini.`);
  }
  if (providers.length !== 1 && providers.length !== workerCount) {
    throw new Error(`agentTypes length must be 1 or ${workerCount}; received ${providers.length}.`);
  }
  return providers as TeamWorkerProvider[];
}

export function resolveRuntimeCliProviderMap(
  raw: string[] | undefined,
  workerCount: number,
): string | null {
  if (!Array.isArray(raw) || raw.length === 0) {
    return null;
  }
  return normalizeAgentTypes(raw, workerCount).join(',');
}

export function resolveRuntimeCliAgentType(raw: string | undefined): string {

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Correct entries to codex|claude|gemini (exact, lowercase; input is lowercased for you)
  2. Trim and filter empty strings when splitting a joined CLI value before calling
  3. Check for renamed providers in release notes if the value used to work

Example fix

// before
const providers = normalizeAgentTypes(userArg.split(','), workerCount);
// after
const providers = normalizeAgentTypes(userArg.split(',').map(s => s.trim()).filter(Boolean), workerCount);
Defensive patterns

Strategy: validation

Validate before calling

const VALID = new Set(['codex','claude','gemini']);
const cleaned = raw.map(s => s.trim().toLowerCase()).filter(Boolean);
if (!cleaned.every(s => VALID.has(s))) throw new Error(`unsupported provider; valid: ${[...VALID].join('|')}`);

Type guard

const isProvider = (s: string): s is TeamWorkerProvider => ['codex','claude','gemini'].includes(s.trim().toLowerCase());

Try / catch

try { normalizeAgentTypes(raw, n); } catch (e) { if (e instanceof Error && e.message.startsWith('Invalid agentTypes')) { /* prompt user with valid options */ } throw e; }

Prevention

When it happens

Trigger: Calling normalizeAgentTypes(['gpt4']) or passing a CLI-provided --agentTypes value like 'codex,openai'; also an empty string entry from a trailing comma split.

Common situations: Typos in CLI flags, provider names from an older version (new provider added/renamed), or naive string splitting of a comma-joined list producing empty entries.

Related errors


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