Yeachan-Heo/oh-my-codex · error · Error
Structured question returned no answer.
Error message
Structured question returned no answer.
What it means
primaryStructuredAnswer() extracts the answer from a structured question response by reading response.answers[0].answer, falling back to response.answer. If both are missing/empty, the guided autoresearch flow cannot proceed and throws.
Source
Thrown at src/cli/autoresearch-guided.ts:59
export interface AutoresearchStructuredQuestionInput {
header?: string;
question: string;
options: Array<{ label: string; value: string; description?: string }>;
allow_other: boolean;
other_label?: string;
multi_select?: boolean;
type?: QuestionType;
source?: string;
}
export type AutoresearchStructuredQuestionAsker = (
input: AutoresearchStructuredQuestionInput,
) => Promise<OmxQuestionSuccessPayload>;
function primaryStructuredAnswer(response: OmxQuestionSuccessPayload): OmxQuestionSuccessPayload["answers"][number]["answer"] {
const answer = response.answers[0]?.answer ?? response.answer;
if (!answer) throw new Error("Structured question returned no answer.");
return answer;
}
function createQuestionIO(): AutoresearchQuestionIO {
const rl = createInterface({ input: process.stdin, output: process.stdout });
return {
question(prompt: string) {
return rl.question(prompt);
},
close() {
rl.close();
},
};
}
async function promptWithDefault(
io: AutoresearchQuestionIO,
prompt: string,View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Inspect the OmxQuestionSuccessPayload returned by the asker to see where the answer actually lives (answers[0].answer vs answer)
- If using a custom asker/mock, ensure it returns at least one entry in answers with a non-empty answer field
- In non-interactive automation, provide the answer directly instead of relying on the structured question path
- Wrap calls in try-catch and fall back to the plain readline io.question path
Example fix
// before
const asker = async () => ({ answers: [] });
// after
const asker = async () => ({ answers: [{ id: 'q1', answer: { value: 'launch' } }] }); Defensive patterns
Strategy: type-guard
Validate before calling
const resp = await asker(input);
if (!resp.answers?.[0]?.answer && !resp.answer) {
throw new RetryableError('question backend returned no answer; retry or use interactive path');
} Type guard
function hasStructuredAnswer(r: OmxQuestionSuccessPayload): boolean {
return Boolean(r.answers?.[0]?.answer ?? r.answer);
} Try / catch
try { return primaryStructuredAnswer(resp); } catch (e) { if (e.message === 'Structured question returned no answer.') return await io.question(promptText); throw e; } Prevention
- Validate asker responses in tests with fixture payloads containing answers
- Prefer constrained single-question prompts
When it happens
Trigger: A structured question asker (the OMX question API invoked with createStructuredQuestionAsker) returns a success payload whose answers array is empty and which has no top-level answer field — e.g. a respondent skipped the question or a stub/mock asker returned an empty success object.
Common situations: Non-interactive contexts where the question backend returns an empty payload, mocks in tests returning {answers: []}, or upstream format changes where the answer lives under a different key.
Related errors
- Structured question returned an invalid next-step answer.
- Structured questions are unavailable in the current OMX work
- No autoresearch-goal mission found at ${repoRelative(cwd, pa
- Invalid autoresearch-goal mission at ${repoRelative(cwd, pat
- Autoresearch goal ${mission.slug} is already complete; creat
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/db9eaefda8f7421b.
Report an issue: GitHub.