can1357/oh-my-pi · warning · SearchProviderError
Codex returned image-only response
Error message
Codex returned image-only response
What it means
After filtering out image-placeholder prose (answers that only contain placeholder text for images instead of real content), if the provider produced no usable final or streamed answer text and collected zero sources, callCodexSearch throws a SearchProviderError with status 502. This indicates the model returned a response consisting only of images/placeholder content, giving the caller nothing to return as a search result.
Source
Thrown at packages/coding-agent/src/web/search/providers/codex.ts:669
}
}
if (!webSearchInvoked) {
throw new CodexNoWebSearchError();
}
const finalAnswer = answerParts.join("\n\n").trim();
const streamedAnswer = streamedAnswerParts.join("").trim();
// Throw to advance the chain whenever Codex emitted nothing but image
// placeholder prose — including the case where the streamed delta itself
// is the placeholder (the model occasionally streams the same text it
// publishes as the final output_text).
const finalIsPlaceholder = finalAnswer.length > 0 && isImagePlaceholderAnswer(finalAnswer);
const streamedIsPlaceholder = streamedAnswer.length > 0 && isImagePlaceholderAnswer(streamedAnswer);
const hasFinalText = finalAnswer.length > 0 && !finalIsPlaceholder;
const hasStreamedText = streamedAnswer.length > 0 && !streamedIsPlaceholder;
if (!hasFinalText && !hasStreamedText && sources.length === 0) {
throw new SearchProviderError("codex", "Codex returned image-only response", 502);
}
const answer = hasFinalText ? finalAnswer : hasStreamedText ? streamedAnswer : "";
// Fallback: when Codex omits url_citation annotations, scrape markdown links
// and bare URLs from the synthesized answer so callers still receive sources.
if (sources.length === 0 && answer.length > 0) {
for (const source of extractTextSources(answer)) {
addSource(sources, source);
}
}
return {
answer,
sources,
model,
requestId,
usage,
};View on GitHub (pinned to 9690622007)
Solutions
- Retry the query — this is often transient model behavior; rephrase to request text-based findings.
- Let the provider fallback chain advance by catching SearchProviderError and trying the next provider.
- Update to a newer version if the backend changed output shape (placeholder detection may need updating).
- Switch to a text-first provider (Brave, Tavily) for queries prone to image-only answers.
Example fix
// before
const res = await searchCodex(params); // throws on image-only
// after
try {
const res = await searchCodex(params);
} catch (e) {
if (e instanceof SearchProviderError && e.status === 502) return fallbackProvider(params);
throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
// nothing to validate pre-call; validate post-hoc before consuming:
function hasUsableResult(r: SearchResponse): boolean {
return Boolean(r.answer?.trim()) || r.sources.length > 0;
} Type guard
function isImageOnlyCodexResponse(e: unknown): e is SearchProviderError {
return e instanceof SearchProviderError && e.provider === "codex" && e.message === "Codex returned image-only response";
} Try / catch
try {
const res = await searchCodex(params);
if (!hasUsableResult(res)) return fallbackProvider(params);
return res;
} catch (e) {
if (isImageOnlyCodexResponse(e)) return fallbackProvider(params);
throw e;
} Prevention
- Treat this as transient and design search callers to advance the provider chain on 502.
- Avoid queries that skew image-only, or append text-oriented directives.
- Keep the package updated so placeholder detection tracks backend output changes.
When it happens
Trigger: The Codex stream completes with web_search_call events but every output_text item (and streamed delta) matches isImagePlaceholderAnswer, and no url_citation annotations or web_search_call sources were collected.
Common situations: Model behavior quirks where the search response is dominated by generated images; backend changes that emit image placeholder prose instead of synthesized text; queries whose results are image-only.
Related errors
- Codex request failed (${code}): ${message || "Request failed
- Codex returned a completion without running web search (no w
- Codex live signaling returned an empty SDP answer
- No Codex web search model is configured.
- No Codex OAuth credentials found. Login with 'omp /login ope
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f6d8763fcb393e54.
Report an issue: GitHub.