paperclipai/paperclip · error · PhotonAnswerValidationError

Choose one option

Error message

Choose one option

What it means

PhotonAnswerValidationError thrown when a question with selectionMode 'single' receives a numeric answer selecting more than one option number. Single-select questions accept exactly one option number.

Solutions

  1. Send exactly one option number for single-select questions
  2. Check question.selectionMode before composing the answer; use multi numbers only when it is 'multiple'
  3. If multiple selections are genuinely intended, change the question's selectionMode to 'multiple' and republish

Example fix

// before
await answer(interaction, index, "1 2");
// after
const value = question.selectionMode === "single" ? "1" : "1 2";
await answer(interaction, index, value);
Defensive patterns

Strategy: validation

Validate before calling

if (question.selectionMode === 'single' && selectedNumbers.length !== 1) throw new Error('choose exactly one option');

Try / catch

try { return parsePhotonQuestionAnswer(interaction, i, value); } catch (e) { if (e instanceof PhotonAnswerValidationError && e.message === 'Choose one option') return enforceSingleSelect(question); throw e; }

Prevention

When it happens

Trigger: Calling parsePhotonQuestionAnswer with multiple numbers (e.g. "1 3") on a question whose payload has selectionMode === 'single'.

Common situations: UI allows multi-select controls for a single-select question; agent tries to select several options in one answer; question type changed from multi to single after the UI rendered.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

  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)
    )
      throw new PhotonAnswerValidationError(
        "Choose valid option numbers without duplicates",
      );
    if (question.selectionMode === "single" && numbers.length !== 1)
      throw new PhotonAnswerValidationError("Choose one option");
    if (numbers.some((index) => question.options[index - 1].freeText))
      throw new PhotonAnswerValidationError("Write your custom answer as text");
    return {
      questionId: question.id,
      optionIds: numbers.map((index) => question.options[index - 1].id),
    };
  }
  const freeText = question.options.find((option) => option.freeText);
  if (question.options.length && question.allowOther === false && !freeText)
    throw new PhotonAnswerValidationError(
      "Answer with the option number(s) shown in the prompt",
    );
  return {
    questionId: question.id,
    optionIds: freeText ? [freeText.id] : [],
    otherText: value,
  };
}

View on GitHub (pinned to 3f1d897a7c)