{"record":{"id":"fd7a61b33f06a96f","repo":"Yeachan-Heo/oh-my-codex","slug":"answers-index-answer-must-include-selected-lab","errorCode":null,"errorMessage":"answers[${index}].answer must include selected_labels[] and selected_values[]","messagePattern":"answers\\[(.+?)\\]\\.answer must include selected_labels\\[\\] and selected_values\\[\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/question/events.ts","lineNumber":228,"sourceCode":"  if (rawAnswers.length === 0) throw new Error('answer payload must include answer or answers[]');\n  const validQuestionIds = new Set((record.questions ?? []).map((question) => question.id));\n  if (validQuestionIds.size === 0) validQuestionIds.add('q-1');\n  const seen = new Set<string>();\n\n  return rawAnswers.map((entry, index) => {\n    if (!entry || typeof entry !== 'object' || Array.isArray(entry)) throw new Error(`answers[${index}] must be an object`);\n    const object = entry as Record<string, unknown>;\n    const questionId = safeString(object.question_id) || (record.questions?.[index]?.id ?? (index === 0 ? 'q-1' : ''));\n    if (!questionId || !validQuestionIds.has(questionId)) throw new Error(`answers[${index}].question_id is unknown for this question: ${questionId || '<missing>'}`);\n    if (seen.has(questionId)) throw new Error(`answers question_id must be unique: ${questionId}`);\n    seen.add(questionId);\n    const answer = object.answer;\n    if (!answer || typeof answer !== 'object' || Array.isArray(answer)) throw new Error(`answers[${index}].answer must be an object`);\n    const answerObject = answer as Record<string, unknown>;\n    const kind = safeString(answerObject.kind);\n    if (!['option', 'other', 'multi'].includes(kind)) throw new Error(`answers[${index}].answer.kind must be option, other, or multi`);\n    if (!Array.isArray(answerObject.selected_labels) || !Array.isArray(answerObject.selected_values)) {\n      throw new Error(`answers[${index}].answer must include selected_labels[] and selected_values[]`);\n    }\n    return {\n      question_id: questionId,\n      index: Number.isInteger(object.index) ? object.index as number : index,\n      answer: answerObject as unknown as QuestionAnswerEntry['answer'],\n    };\n  });\n}\n","sourceCodeStart":210,"sourceCodeEnd":237,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/question/events.ts#L210-L237","documentation":"Thrown by normalizeSubmittedAnswers after kind validation passes. Every submitted answer must carry selected_labels and selected_values as actual arrays, since the renderer and result aggregation iterate both. If either is missing or not an array (e.g. a string or object), this error is raised with the offending index.","triggerScenarios":"Submitting answers[i].answer with kind 'option'/'other'/'multi' but omitting selected_labels or selected_values, or sending them as strings/objects (e.g. selected_labels: 'Yes' instead of ['Yes']).","commonSituations":"Minimal hand-written payloads that only include a value; clients that model single-select as a scalar instead of a one-element array; copying example JSON that predates the two-array schema.","solutions":["Add both arrays: selected_labels: string[] and selected_values: string[].","Wrap scalar selections in arrays (selected_values: ['yes'], not selected_values: 'yes').","Run normalizeSubmittedAnswers on a sample payload during development to catch shape drift early."],"exampleFix":"// before\nanswer: { kind: 'option', selected_values: 'yes' }\n\n// after\nanswer: { kind: 'option', selected_labels: ['Yes'], selected_values: ['yes'] }","handlingStrategy":"validation","validationCode":"const ok = answers.every((e, i) =>\n  Array.isArray(e?.answer?.selected_labels) &&\n  Array.isArray(e?.answer?.selected_values)\n);","typeGuard":"function hasSelectionArrays(a: unknown): a is { selected_labels: string[]; selected_values: string[] } {\n  const o = a as Record<string, unknown>;\n  return Array.isArray(o?.selected_labels) && Array.isArray(o?.selected_values);\n}","tryCatchPattern":"try { await result({ answers }); } catch (e) { if (e instanceof Error && /selected_labels\\[\\] and selected_values\\[\\]/.test(e.message)) { /* backfill missing arrays */ } else throw e; }","preventionTips":["Always wrap selections in arrays, even single-select (one-element arrays).","Add a zod schema: z.object({ kind: z.enum(['option','other','multi']), selected_labels: z.array(z.string()), selected_values: z.array(z.string()) }).","Assert payload shape in tests before submitting."],"tags":["schema-validation","answers","arrays"],"backgroundTag":"schema-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}