paperclipai/paperclip · error · Error
Discord form correction is not current
Error message
Discord form correction is not current
What it means
retainDiscordQuestionFormCorrection validates a Discord modal-based form correction before persisting it. This error means the submitted correction is stale or structurally out of date: the binding has expired, or the modal's callback ID / private metadata no longer match the submit action ID, or the modal has an invalid number of children (Discord requires 1-5 inputs). It prevents replaying or tampering with old form corrections.
Source
Thrown at server/src/services/chat-discord-question-forms.ts:163
values: Record<string, string>;
},
now = new Date(),
): Promise<DiscordModalCorrectionResponse> {
const expiresAt = new Date(
Math.min(
Date.parse(input.parentExpiresAt),
now.getTime() + CORRECTION_TTL_MS,
),
);
if (
!Number.isFinite(expiresAt.getTime()) ||
expiresAt <= now ||
input.modal.callbackId !== input.submitActionId ||
input.modal.privateMetadata !== input.submitActionId ||
input.modal.children.length < 1 ||
input.modal.children.length > 5
)
throw new Error("Discord form correction is not current");
const values: Record<string, string> = {};
const messages: string[] = [
"Please check your answers, then select Edit answers.",
];
for (const child of input.modal.children) {
if (child.type !== "text_input" && child.type !== "select")
throw new Error("Unsupported Discord correction field");
const value = input.values[child.id];
const error = input.fieldErrors[child.id];
// Both label and error are produced by canonical form validation, never
// provider labels/error bodies. Opaque input IDs are not visible copy.
if (error) messages.push(`${child.label}: ${error}`);
if (typeof value !== "string") continue;
if (child.type === "text_input") {
const maximum = Math.min(child.maxLength ?? 4000, 4000);
values[child.id] = value.slice(0, maximum);
if (value.length > maximum)
messages.push(View on GitHub (pinned to 01ad858492)
Solutions
- Discard the stale draft and re-issue a fresh question form so a new modal/correction binding is generated
- Check that the modal's custom_id (callbackId) and private_metadata are both set to the current submitActionId when constructing the modal
- Ensure the modal has between 1 and 5 child inputs before submitting the correction
- If expiry is the issue, ask the user to resubmit promptly or extend the binding's expiry window
Example fix
// before modal.children = sixInputs; // 6 children // after modal.children = sixInputs.slice(0, 5); // Discord allows max 5 inputs per modal
Defensive patterns
Strategy: validation
Validate before calling
function isCorrectionCurrent(input, now) {
return input.expiresAt > now &&
input.modal.callbackId === input.submitActionId &&
input.modal.privateMetadata === input.submitActionId &&
input.modal.children.length >= 1 &&
input.modal.children.length <= 5;
}
if (!isCorrectionCurrent(input, Date.now())) return promptFreshForm(); Type guard
const isCurrentModal = (m) => m && typeof m.callbackId === "string" && m.callbackId === m.privateMetadata && Array.isArray(m.children) && m.children.length >= 1 && m.children.length <= 5;
Prevention
- Build modals with 1-5 children and assert this in the form builder
- Set callbackId and privateMetadata to the same submitActionId at construction time
- Show users an expiry warning before the binding expires; re-issue forms proactively
- Treat Discord interaction duplicates as idempotent by interaction id
When it happens
Trigger: Submitting a Discord modal whose expiresAt is in the past; a modal whose callbackId or private_metadata does not equal the submitActionId; a modal built with zero children or more than 5 children.
Common situations: A user takes too long to answer the modal and it expires; a Discord interaction replay/duplicate delivery re-submits an old callback ID; a developer builds a modal with 6+ text inputs, which Discord rejects structurally.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Invalid Discord command owner identifier
- Invalid Discord command registration scope
- invalid_response
- Invalid Discord command registration authority
- Invalid Discord form token
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/bfac0b8f0643696b.
Report an issue: GitHub.