paperclipai/paperclip · error · PhotonAnswerValidationError

That question does not exist

Error message

That question does not exist

What it means

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.

Solutions

  1. Validate questionIndex against interaction.payload.questions.length before submitting
  2. Use the question's id to locate its index instead of hardcoding a number
  3. Refetch the current interaction payload and re-render the questions before answering

Example fix

// before
parsePhotonQuestionAnswer(interaction, questionIndex, value);
// after
if (questionIndex < 0 || questionIndex >= interaction.payload.questions.length) return;
parsePhotonQuestionAnswer(interaction, questionIndex, value);
Defensive patterns

Strategy: validation

Validate before calling

const isValidIndex = (i: number, ia: { payload: { questions: unknown[] } }) => Number.isInteger(i) && i >= 0 && i < ia.payload.questions.length;

Type guard

const getQuestion = (ia: AskUserQuestionsInteraction, i: number) => ia.payload.questions[i] ?? null;

Try / catch

try { return parsePhotonQuestionAnswer(interaction, i, value); } catch (e) { if (e instanceof PhotonAnswerValidationError && e.message === 'That question does not exist') return refetchAndRe-render(); throw e; }

Prevention

When it happens

Trigger: Calling parsePhotonQuestionAnswer (via processPhotonResponse) with a questionIndex >= questions.length, < 0, or against a sparse questions array.

Common situations: 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.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/eef7ea34059f2594. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/photon/interactions.ts:83

    /^\/(answer|submit)\s+([a-zA-Z0-9_-]{8,24})(?:\.(\d{1,2}))?(?:\s+([\s\S]*))?$/i.exec(
      text.trim(),
    );
  if (!match) return null;
  return {
    command: match[1].toLowerCase() as "answer" | "submit",
    reference: match[2],
    questionIndex: Number(match[3] ?? 1) - 1,
    value: match[4]?.trim() ?? "",
  };
}
export function parsePhotonQuestionAnswer(
  interaction: AskUserQuestionsInteraction,
  questionIndex: number,
  value: string,
): AskUserQuestionsAnswer {
  const question = interaction.payload.questions[questionIndex];
  if (!question)
    throw new PhotonAnswerValidationError("That question does not exist");
  if (value.toLowerCase() === "skip") {
    if (question.required !== false)
      throw new PhotonAnswerValidationError("This question requires an answer");
    return { questionId: question.id, optionIds: [] };
  }
  if (!value || value.length > 100_000)
    throw new PhotonAnswerValidationError(
      "Enter a nonempty answer within the task’s length limit",
    );
  const numbers =
    /^\d+(?:[ ,]+\d+)*$/.test(value) &&
    question.options.some((option) => !option.freeText)
      ? value.split(/[ ,]+/).map(Number)
      : null;
  if (numbers) {
    if (
      new Set(numbers).size !== numbers.length ||
      numbers.some((index) => index < 1 || index > question.options.length)

View on GitHub (pinned to 3f1d897a7c)