paperclipai/paperclip · error · Error
Invalid Discord form token
Error message
Invalid Discord form token
What it means
correctionId() in chat-discord-question-forms.ts derives the storage key for a question-form correction retry from a submitActionId that must be a high-entropy token of the exact form 'pcfs:' + 22 chars of [A-Za-z0-9_-]. Anything else throws 'Invalid Discord form token', refusing to build a correction id from an untrusted identifier.
Source
Thrown at server/src/services/chat-discord-question-forms.ts:58
}
const token = (value: unknown, prefix: string, length = 22): value is string =>
typeof value === "string" &&
new RegExp(`^${prefix}[A-Za-z0-9_-]{${length}}$`).test(value);
export function isDiscordQuestionFormCorrectionId(
value: unknown,
): value is string {
return token(value, "pcfr:", 43);
}
function correctionId(
scope: ChatSdkStateScope,
owner: DiscordQuestionFormDraftOwner,
submitActionId: string,
) {
if (!token(submitActionId, "pcfs:"))
throw new Error("Invalid Discord form token");
// Includes the high-entropy secret submit token, not merely public IDs. One
// overwritable row per form+actor bounds retry storage without persisting a
// Discord interaction token or raw callback envelope.
return `pcfr:${createHash("sha256")
.update(
JSON.stringify([
scope.companyId,
scope.endpointId,
submitActionId,
owner.principalId,
owner.userId,
owner.externalUserId,
]),
)
.digest("base64url")}`;
}
function validDraft(View on GitHub (pinned to 01ad858492)
Solutions
- Verify the submitActionId was produced by the form-issuing path (isDiscordQuestionForm-style token check) before calling loadDiscordQuestionFormCorrection.
- Fix custom-id parsing so the 'pcfs:...' token is extracted intact (no URL-decoding/trimming/splitting damage).
- Reject bad tokens at the interaction handler entry and re-issue a fresh form instead of attempting correction lookup.
- Log the received token shape (prefix/length only) to identify where corruption happens.
Example fix
// before
const submitActionId = customId.split(":").pop(); // may mangle token
// after
if (!isDiscordQuestionFormSubmitActionId(customId)) return respondInvalid();
const submitActionId = customId.slice("pcqf:".length); // exact token extraction Defensive patterns
Strategy: validation
Validate before calling
const isSubmitActionToken = (v: unknown): v is string =>
typeof v === "string" && /^pcfs:[A-Za-z0-9_-]{22}$/.test(v);
if (!isSubmitActionToken(submitActionId)) throw new Error("malformed pcfs token before correction lookup"); Type guard
const isDiscordFormSubmitToken = (v: unknown): v is string =>
typeof v === "string" && /^pcfs:[A-Za-z0-9_-]{22}$/.test(v); Try / catch
try { const correction = await loadDiscordQuestionFormCorrection(scope, owner, submitActionId); }
catch (e) {
if ((e as Error).message === "Invalid Discord form token") { return respondWithFreshForm(); }
throw e;
} Prevention
- Extract pcfs tokens from custom_ids with exact slicing, not lossy split/decode operations.
- Validate action ids at the interaction-handler entry before any storage lookup.
- Re-issue fresh forms instead of retrying lookups with corrupt tokens.
- Never round-trip tokens through encodings that change length or characters.
When it happens
Trigger: Calling correctionId (via actionId, key, or loadDiscordQuestionFormCorrection) with a submitActionId that is not a string, lacks the 'pcfs:' prefix, has the wrong length (≠22 chars after the prefix), or contains characters outside [A-Za-z0-9_-] — e.g. a raw Discord interaction/custom-id fragment or a truncated/partially-decoded action id.
Common situations: Parsing a Discord component custom_id with the wrong split so the tail still contains separators; passing a legacy/other-format action id; a client submitting a forged or truncated token; storing/round-tripping the action id through something that altered its length or encoding (URL-encoding, trimming).
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- Unsafe ${label}: ${result}
- Invalid normalized OpenCode session id
- Invalid Discord command owner identifier
- sandbox runtime asset key is not a simple path segment: ${ke
- Invalid GitHub launcher run ID
AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10).
Data as JSON: /api/errors/0cd40567a00a008f.
Report an issue: GitHub.