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

entries must be strings

Error message

${fieldName} entries must be strings

What it means

Thrown by parseValidatedTaskIdArray in src/team/api-interop.ts when validating team API operation arguments. It means a field expected to be an array of task IDs contains at least one entry that is not a string (e.g. a number or object). The library enforces strict string arrays before passing task IDs to the CLI interop layer.

Solutions

  1. Convert all task ID entries to strings before calling the API: ids.map(String)
  2. Check your --input JSON payload and quote every task ID value
  3. Validate the array shape with Array.isArray and typeof checks before the call

Example fix

// before
api('update-tasks', { task_ids: [101, 102] });
// after
api('update-tasks', { task_ids: ['101', '102'] });
Defensive patterns

Strategy: validation

Validate before calling

const isTaskIdArray = (v: unknown): v is string[] =>
  Array.isArray(v) && v.every((x) => typeof x === 'string');
if (!isTaskIdArray(args.task_ids)) throw new TypeError('task_ids must be string[]');

Type guard

const isTaskIdArray = (v: unknown): v is string[] =>
  Array.isArray(v) && v.every((x) => typeof x === 'string');

Prevention

When it happens

Trigger: Calling executeTeamApiOperation with a field like task_ids: [101, 102] (numbers) or mixed types instead of ['101','102']. Any non-string element triggers this immediately.

Common situations: JSON input parsed from a hand-crafted file where task IDs were written as unquoted numbers; passing output of another tool that returns numeric IDs directly without mapping to strings.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/team/api-interop.ts:449

    last_team_leader_nudge_event: summarizeEvent(latestLeaderNudgeEvent),
    last_leader_notification_deferred_event: summarizeEvent(latestDeferredEvent),
    source: {
      summary_available: summary !== null,
      snapshot_available: snapshot !== null,
      phase_available: phaseState !== null,
      recent_event_count: recentEvents.length,
    },
  };
}

function parseValidatedTaskIdArray(value: unknown, fieldName: string): string[] {
  if (!Array.isArray(value)) {
    throw new Error(`${fieldName} must be an array of task IDs (strings)`);
  }
  const taskIds: string[] = [];
  for (const item of value) {
    if (typeof item !== 'string') {
      throw new Error(`${fieldName} entries must be strings`);
    }
    const normalized = item.trim();
    if (!TASK_ID_SAFE_PATTERN.test(normalized)) {
      throw new Error(`${fieldName} contains invalid task ID: "${item}"`);
    }
    taskIds.push(normalized);
  }
  return taskIds;
}

function teamStateExists(teamName: string, candidateCwd: string): boolean {
  if (!TEAM_NAME_SAFE_PATTERN.test(teamName)) return false;
  const teamRoot = join(resolveCanonicalTeamStateRoot(candidateCwd), 'team', teamName);
  return existsSync(join(teamRoot, 'config.json')) || existsSync(join(teamRoot, 'tasks')) || existsSync(teamRoot);
}

function readTeamStateRootFromManifest(path: string): string | null {
  if (!existsSync(path)) return null;

View on GitHub (pinned to 3ad79a8a6f)