Yeachan-Heo/oh-my-codex · error · Error
visual_verdict.${field} must contain strings
Error message
visual_verdict.${field} must contain strings What it means
Inside a visual_verdict string-array field, one of the array elements is not a string (number, object, null, boolean). asTrimmedStringArray throws because every element of observations/next_actions must be a string (empty strings are trimmed and filtered, but non-strings are rejected).
Source
Thrown at src/visual/verdict.ts:29
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('|')}`);
}
return normalized as VisualVerdictStatus;
}
export function parseVisualVerdict(input: unknown): VisualVerdict {View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Coerce or drop non-string elements on the producer side before serializing
- Map numeric/null entries to strings (String(item)) or omit them
- Validate model output with a schema before feeding it to parseVisualVerdict
Example fix
// before
{ "observations": ["ok", 42] }
// after
{ "observations": ["ok", "42"] } Defensive patterns
Strategy: type-guard
Validate before calling
if (!arr.every(x => typeof x === 'string')) arr = arr.map(String);
Type guard
const isStringArray = (v: unknown): v is string[] => Array.isArray(v) && v.every(x => typeof x === 'string');
Prevention
- Coerce non-string entries before serialization
- Reject null placeholders in list fields at the source
When it happens
Trigger: Calling parseVisualVerdict where e.g. visual_verdict.next_actions is ["fix css", 3] or [null].
Common situations: LLM output mixing types into arrays (numbers as step indices); JSON produced from untyped languages; verdict fixtures with nulls for empty items.
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
- visual_verdict.${field} must be an array
- Invalid ultragoal plan at ${repoRelative(cwd, path)}.
- Invalid autoresearch-goal mission at ${repoRelative(cwd, pat
- autoresearch candidate artifact must be valid JSON
- autoresearch candidate artifact must be a JSON object
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/ada248b73bc83b8c.
Report an issue: GitHub.