{"record":{"id":"0416658d6912934d","repo":"Yeachan-Heo/oh-my-codex","slug":"answers-entry-index-answer-other-value-must-ma","errorCode":null,"errorMessage":"answers[${entry.index}].answer other value must match selected_values[0] and other_text","messagePattern":"answers\\[(.+?)\\]\\.answer other value must match selected_values\\[0\\] and other_text","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/question/state.ts","lineNumber":374,"sourceCode":"\nfunction validateAnswerAgainstQuestion(question: NormalizedQuestionItem, entry: QuestionAnswerEntry): void {\n  const { answer } = entry;\n  const selectedValues = validateStringArray(answer.selected_values, `answers[${entry.index}].answer.selected_values`);\n  const selectedLabels = validateStringArray(answer.selected_labels, `answers[${entry.index}].answer.selected_labels`);\n  assertNoDuplicateValues(selectedValues, `answers[${entry.index}].answer.selected_values`);\n\n  const optionValues = new Set(question.options.map((option) => option.value));\n  const multi = isMultiAnswerableQuestion(question);\n  const hasOtherText = typeof answer.other_text === 'string' && answer.other_text.trim().length > 0;\n  const otherText = hasOtherText ? answer.other_text!.trim() : undefined;\n  const outOfSchemaValues = selectedValues.filter((value) => !optionValues.has(value));\n\n  if (answer.kind === 'other') {\n    if (!question.allow_other) throw new Error(`answers[${entry.index}].answer.kind=other is not allowed for this question`);\n    if (multi) throw new Error(`answers[${entry.index}].answer.kind=other is only valid for single-answerable questions`);\n    if (!otherText) throw new Error(`answers[${entry.index}].answer.other_text must be a non-empty string`);\n    if (selectedValues.length !== 1 || selectedValues[0] !== otherText || answer.value !== otherText) {\n      throw new Error(`answers[${entry.index}].answer other value must match selected_values[0] and other_text`);\n    }\n    assertSelectedLabelsMatch(\n      selectedLabels,\n      [question.other_label],\n      `answers[${entry.index}].answer.selected_labels`,\n    );\n    return;\n  }\n\n  if (answer.kind === 'option') {\n    if (multi) throw new Error(`answers[${entry.index}].answer.kind=option is only valid for single-answerable questions`);\n    if (selectedValues.length !== 1 || selectedLabels.length !== 1) {\n      throw new Error(`answers[${entry.index}].answer must select exactly one option`);\n    }\n    const selectedValue = selectedValues[0]!;\n    if (!optionValues.has(selectedValue)) {\n      throw new Error(`answers[${entry.index}].answer selected value is not in the option schema: ${selectedValue}`);\n    }","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/question/state.ts#L356-L392","documentation":"For other-kind answers, consistency is enforced: selected_values must have exactly one element equal to the trimmed other_text, and answer.value must equal it too. Any divergence throws this error.","triggerScenarios":"kind 'other' where selected_values[0] !== other_text.trim(), selected_values.length !== 1, or answer.value !== other_text — e.g. sending the matched option value while other_text holds the free text.","commonSituations":"Client setting value/selected_values from a hidden 'other' option value (like '__other__') while other_text holds real text; partial normalization that trims one field but not the other.","solutions":["Set all three fields from one source: const text = input.trim(); value = text; selected_values = [text]; other_text = text","Never use a sentinel like '__other__' as the value; the free text itself is the value"],"exampleFix":"// before\nanswer.value = '__other__'; answer.selected_values = ['__other__']; answer.other_text = text;\n// after\nconst t = text.trim();\nanswer.value = t; answer.selected_values = [t]; answer.other_text = t;","handlingStrategy":"validation","validationCode":"const t = (answer.other_text ?? '').trim();\nif (answer.kind === 'other' && (answer.selected_values.length !== 1 || answer.selected_values[0] !== t || answer.value !== t)) {\n  answer.value = t; answer.selected_values = [t];\n}","typeGuard":"function otherAnswerConsistent(a: QuestionAnswerEntry): boolean {\n  const t = typeof a.answer.other_text === 'string' ? a.answer.other_text.trim() : '';\n  return t.length > 0 && a.answer.selected_values.length === 1 && a.answer.selected_values[0] === t && a.answer.value === t;\n}","tryCatchPattern":"try { await submit(p, answers); } catch (e) { if (/other value must match/.test((e as Error).message)) { syncOtherFieldsFromOtherText(answer); return submit(p, answers); } throw e; }","preventionTips":["Populate value, selected_values and other_text from one trimmed string","Avoid sentinel values like '__other__'"],"tags":["validation","allow-other","consistency"],"backgroundTag":"schema-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}