paperclipai/paperclip · error · PhotonAnswerValidationError

Enter a nonempty answer within the task’s length limit

Error message

Enter a nonempty answer within the task’s length limit

What it means

PhotonAnswerValidationError thrown when the answer is empty or longer than 100,000 characters. parsePhotonQuestionAnswer enforces a nonempty, bounded-length answer for anything that is not a permitted "skip".

Solutions

  1. Ensure the answer is nonempty and <= 100,000 characters before submitting
  2. Truncate or summarize overly long input to fit the 100k limit
  3. If the user genuinely wants to decline, use "skip" only on questions with required: false

Example fix

// before
await answer(interaction, index, userText);
// after
const text = (userText ?? "").slice(0, 100_000);
if (!text) return;
await answer(interaction, index, text);
Defensive patterns

Strategy: validation

Validate before calling

const valid = typeof value === 'string' && value.length > 0 && value.length <= 100_000;

Try / catch

try { return parsePhotonQuestionAnswer(interaction, i, value); } catch (e) { if (e instanceof PhotonAnswerValidationError && /nonempty/.test(e.message)) return truncateAndRetry(value.slice(0, 100_000)); throw e; }

Prevention

When it happens

Trigger: Calling parsePhotonQuestionAnswer with value = "" or a string whose length exceeds 100000, for any non-skippable answer.

Common situations: An upstream agent submits an empty response when the user gave none; pasting a very large document (logs, dumps) as the answer; a null/undefined coerced to empty string before the call.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


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

Appendix: source

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

    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)
    )
      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))

View on GitHub (pinned to 3f1d897a7c)