paperclipai/paperclip · error · Error

Invalid Discord correction binding

Error message

Invalid Discord correction binding

What it means

After constructing the DiscordQuestionFormCorrectionDraft from the binding, the code re-validates it with validDraft(draft). This error means the assembled draft failed internal validation — e.g. the spread binding plus version/expiresAt/values produced a structurally invalid draft, or input.values contained entries that don't validate.

Source

Thrown at server/src/services/chat-discord-question-forms.ts:200

          `${child.label}: This draft was shortened to ${maximum} characters.`,
        );
    } else if (child.options.some((option) => option.value === value))
      values[child.id] = value;
  }
  const {
    modal: _modal,
    values: _values,
    fieldErrors: _errors,
    parentExpiresAt: _expiry,
    ...binding
  } = input;
  const draft: DiscordQuestionFormCorrectionDraft = {
    ...binding,
    version: 1,
    expiresAt: expiresAt.toISOString(),
    values,
  };
  if (!validDraft(draft)) throw new Error("Invalid Discord correction binding");
  const actionId = correctionId(scope, input, input.submitActionId);
  for (let attempt = 0; attempt < MAX_CAS_ATTEMPTS; attempt++) {
    const prior = await persistence.read(scope, stateKey(actionId));
    if (
      await persistence.compareAndSet({
        ...scope,
        key: stateKey(actionId),
        expectedVersion: prior?.version ?? null,
        value: draft,
        expiresAt,
      })
    ) {
      return {
        action: "errors",
        errors: input.fieldErrors,
        paperclipDiscordCorrection: {
          version: 1,
          actionId,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Log the draft passed to validDraft and fix the caller supplying the binding so all required fields are present and correctly typed
  2. Re-issue a fresh correction flow instead of reusing a stored binding that no longer matches the current draft schema
  3. Check for schema migrations between draft versions and migrate old stored bindings

Example fix

// before
const draft = { ...maybePartialBinding, version: 1 };
// after
if (!binding || typeof binding.values !== "object") throw new Error("binding incomplete");
const draft = { ...binding, version: 1, expiresAt: expiresAt.toISOString(), values };
Defensive patterns

Strategy: validation

Validate before calling

function validateBinding(binding) {
  return binding && typeof binding === "object" &&
    typeof binding.values === "object" && binding.values !== null &&
    typeof binding.expiresAt === "string" && !isNaN(Date.parse(binding.expiresAt));
}
if (!validateBinding(inputBinding)) throw new Error("binding incomplete before retain");

Type guard

const isDraftLike = (d) => !!d && typeof d === "object" && typeof d.version === "number" && typeof d.expiresAt === "string" && typeof d.values === "object";

Try / catch

try {
  await retainDiscordQuestionFormCorrection(...);
} catch (err) {
  if (err.message === "Invalid Discord correction binding") {
    // restart the correction flow with a fresh binding
    return startFreshCorrection(scope, input);
  }
  throw err;
}

Prevention

When it happens

Trigger: The binding object passed into retainDiscordQuestionFormCorrection is missing required fields or has wrong types; values derived from the modal do not satisfy validDraft's invariants (e.g. non-string or disallowed values); expiresAt serialization is malformed.

Common situations: A caller passes a partially-constructed or corrupted binding loaded from persistence; a schema migration changed the draft shape so older stored bindings no longer validate; a bug in value coercion produces an invalid draft.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/832d0c27530570b4. Report an issue: GitHub.