{"record":{"id":"9d621b413e9af75b","repo":"Yeachan-Heo/oh-my-codex","slug":"please-choose-either-launch-or-refine-further","errorCode":null,"errorMessage":"Please choose either \"launch\" or \"refine further\".","messagePattern":"Please choose either \"launch\" or \"refine further\"\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/autoresearch-guided.ts","lineNumber":156,"sourceCode":"\t\t\t? answer.value.trim().toLowerCase()\n\t\t\t: \"\";\n\t\tif (answerValue === \"launch\") return \"launch\";\n\t\tif (answerValue === \"refine\") return \"refine\";\n\t\tthrow new Error('Structured question returned an invalid next-step answer.');\n\t}\n\n\tconst answer = (\n\t\tawait io.question(\n\t\t\t`\\nNext step [launch/refine further] (default: ${launchReady ? \"launch\" : \"refine further\"})\\n> `,\n\t\t)\n\t)\n\t\t.trim()\n\t\t.toLowerCase();\n\tif (!answer) return launchReady ? \"launch\" : \"refine\";\n\tif (answer === \"launch\") return \"launch\";\n\tif (answer === \"refine further\" || answer === \"refine\" || answer === \"r\")\n\t\treturn \"refine\";\n\tthrow new Error('Please choose either \"launch\" or \"refine further\".');\n}\n\nfunction createStructuredQuestionAsker(\n\trepoRoot: string,\n): AutoresearchStructuredQuestionAsker {\n\treturn (input) =>\n\t\trunDeepInterviewQuestion(\n\t\t\t{\n\t\t\t\theader: input.header,\n\t\t\t\tquestion: input.question,\n\t\t\t\toptions: input.options,\n\t\t\t\tallow_other: input.allow_other,\n\t\t\t\tother_label: input.other_label ?? \"Other\",\n\t\t\t\ttype: input.type,\n\t\t\t\tmulti_select: input.multi_select ?? false,\n\t\t\t\tsource: input.source ?? \"deep-interview\",\n\t\t\t},\n\t\t\t{ cwd: repoRoot },","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/autoresearch-guided.ts#L138-L174","documentation":"In the interactive (non-structured) branch of promptAction(), the user's typed next-step input must be empty (default), 'launch', or one of 'refine further'/'refine'/'r' (case-insensitive). Anything else throws immediately without re-prompting.","triggerScenarios":"A user typing 'go', 'yes', 'l', 'start', or any unrecognized text at the 'Next step [launch/refine further]' prompt.","commonSituations":"Users abbreviating beyond the accepted aliases (only 'r' is accepted for refine; 'l' is not accepted for launch), or piped stdin containing unexpected text.","solutions":["Type exactly 'launch' or 'refine' (or press Enter to accept the default shown in the prompt)","When piping input non-interactively, echo one of the accepted tokens or an empty line","If scripting, prefer the structured-question path with constrained answers"],"exampleFix":"# before\necho 'go' | omx autoresearch ...\n# after\necho 'launch' | omx autoresearch ...","handlingStrategy":"validation","validationCode":"const raw = (await io.question('Next step [launch/refine further]\\n> ')).trim().toLowerCase();\nconst ok = raw === '' || raw === 'launch' || ['refine further','refine','r'].includes(raw);\nif (!ok) { /* re-prompt instead of failing */ }","typeGuard":"const isNextStep = (s: string): s is 'launch'|'refine' => {\n  const v = s.trim().toLowerCase();\n  return v === 'launch' || v === 'refine' || v === 'refine further' || v === 'r';\n};","tryCatchPattern":"try { return await promptAction(io); } catch (e) { if (e.message.includes('launch or refine')) { printAcceptedValues(); return await promptAction(io); } throw e; }","preventionTips":["Tell users the accepted tokens in surrounding docs","When piping stdin, send 'launch', 'refine', or an empty line"],"tags":["interactive-prompt","invalid-input","autoresearch"],"backgroundTag":"invalid-user-choice","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}