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

visual_verdict.${field} must be an array

Error message

visual_verdict.${field} must be an array

What it means

parseVisualVerdict validates a visual_verdict object; asTrimmedStringArray throws when a field expected to be a string array (e.g. observations, next_actions) is not an Array. The parser strictly enforces the verdict schema before use.

Source

Thrown at src/visual/verdict.ts:24

export interface VisualVerdict {
  score: number;
  verdict: VisualVerdictStatus;
  category_match: boolean;
  differences: string[];
  suggestions: string[];
  reasoning: string;
}

export interface VisualLoopFeedback extends VisualVerdict {
  threshold: number;
  passes_threshold: boolean;
  next_actions: string[];
}

function asTrimmedStringArray(value: unknown, field: string): string[] {
  if (!Array.isArray(value)) {
    throw new Error(`visual_verdict.${field} must be an array`);
  }
  return value
    .map((item) => {
      if (typeof item !== 'string') {
        throw new Error(`visual_verdict.${field} must contain strings`);
      }
      return item.trim();
    })
    .filter((item) => item.length > 0);
}

function parseVisualVerdictStatus(value: unknown): VisualVerdictStatus {
  if (typeof value !== 'string') {
    throw new Error(`visual_verdict.verdict must be one of: ${VISUAL_VERDICT_STATUSES.join('|')}`);
  }
  const normalized = value.trim().toLowerCase();
  if (!VISUAL_VERDICT_STATUSES.includes(normalized as VisualVerdictStatus)) {
    throw new Error(`visual_verdict.verdict must be one of: ${VISUAL_VERDICT_STATUSES.join('|')}`);

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Fix the producer to emit arrays for observations/next_actions (possibly empty arrays)
  2. If wrapping model output, coerce string values into [string] before parsing
  3. Add a schema check (e.g. zod) on the verdict producer side

Example fix

// before
{ "verdict": "fail", "observations": "header misaligned", "next_actions": "fix css" }
// after
{ "verdict": "fail", "observations": ["header misaligned"], "next_actions": ["fix css"] }
Defensive patterns

Strategy: type-guard

Validate before calling

for (const f of ['observations','next_actions']) if (!Array.isArray(verdict[f])) verdict[f] = [verdict[f]].filter(v => v != null).map(String);

Type guard

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

Prevention

When it happens

Trigger: Calling parseVisualVerdict on a JSON object where visual_verdict.observations or visual_verdict.next_actions is a string, object, null, or undefined instead of an array.

Common situations: LLM/visual-agent output that emits a comma-separated string instead of an array; hand-edited verdict JSON; downstream producers whose schema drifted (e.g. renamed or restructured fields).

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/0581ab11a0f7523c. Report an issue: GitHub.