{"record":{"id":"eef7ea34059f2594","repo":"paperclipai/paperclip","slug":"that-question-does-not-exist","errorCode":null,"errorMessage":"That question does not exist","messagePattern":"That question does not exist","errorType":"validation","errorClass":"PhotonAnswerValidationError","httpStatus":null,"severity":"error","filePath":"server/src/services/photon/interactions.ts","lineNumber":83,"sourceCode":"    /^\\/(answer|submit)\\s+([a-zA-Z0-9_-]{8,24})(?:\\.(\\d{1,2}))?(?:\\s+([\\s\\S]*))?$/i.exec(\n      text.trim(),\n    );\n  if (!match) return null;\n  return {\n    command: match[1].toLowerCase() as \"answer\" | \"submit\",\n    reference: match[2],\n    questionIndex: Number(match[3] ?? 1) - 1,\n    value: match[4]?.trim() ?? \"\",\n  };\n}\nexport function parsePhotonQuestionAnswer(\n  interaction: AskUserQuestionsInteraction,\n  questionIndex: number,\n  value: string,\n): AskUserQuestionsAnswer {\n  const question = interaction.payload.questions[questionIndex];\n  if (!question)\n    throw new PhotonAnswerValidationError(\"That question does not exist\");\n  if (value.toLowerCase() === \"skip\") {\n    if (question.required !== false)\n      throw new PhotonAnswerValidationError(\"This question requires an answer\");\n    return { questionId: question.id, optionIds: [] };\n  }\n  if (!value || value.length > 100_000)\n    throw new PhotonAnswerValidationError(\n      \"Enter a nonempty answer within the task’s length limit\",\n    );\n  const numbers =\n    /^\\d+(?:[ ,]+\\d+)*$/.test(value) &&\n    question.options.some((option) => !option.freeText)\n      ? value.split(/[ ,]+/).map(Number)\n      : null;\n  if (numbers) {\n    if (\n      new Set(numbers).size !== numbers.length ||\n      numbers.some((index) => index < 1 || index > question.options.length)","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/photon/interactions.ts#L65-L101","documentation":"PhotonAnswerValidationError thrown by parsePhotonQuestionAnswer when the supplied questionIndex does not resolve to a question in interaction.payload.questions (undefined element). The library validates the index before parsing the answer so answers cannot be attributed to a nonexistent question.","triggerScenarios":"Calling parsePhotonQuestionAnswer (via processPhotonResponse) with a questionIndex >= questions.length, < 0, or against a sparse questions array.","commonSituations":"UI sends a stale index after the prompt was republished with fewer questions; off-by-one indexing (using 1-based numbers straight from the prompt); a race where the interaction payload was updated between display and answer submission.","solutions":["Validate questionIndex against interaction.payload.questions.length before submitting","Use the question's id to locate its index instead of hardcoding a number","Refetch the current interaction payload and re-render the questions before answering"],"exampleFix":"// before\nparsePhotonQuestionAnswer(interaction, questionIndex, value);\n// after\nif (questionIndex < 0 || questionIndex >= interaction.payload.questions.length) return;\nparsePhotonQuestionAnswer(interaction, questionIndex, value);","handlingStrategy":"validation","validationCode":"const isValidIndex = (i: number, ia: { payload: { questions: unknown[] } }) => Number.isInteger(i) && i >= 0 && i < ia.payload.questions.length;","typeGuard":"const getQuestion = (ia: AskUserQuestionsInteraction, i: number) => ia.payload.questions[i] ?? null;","tryCatchPattern":"try { return parsePhotonQuestionAnswer(interaction, i, value); } catch (e) { if (e instanceof PhotonAnswerValidationError && e.message === 'That question does not exist') return refetchAndRe-render(); throw e; }","preventionTips":["Always bounds-check questionIndex against questions.length","Locate questions by id, not hardcoded index","Refetch the interaction payload before answering after any republish"],"tags":["validation","index-out-of-bounds","interaction"],"backgroundTag":"index-out-of-bounds","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}