{"record":{"id":"a76c900658ba8d86","repo":"paperclipai/paperclip","slug":"invalid-discord-command-registration-scope","errorCode":null,"errorMessage":"Invalid Discord command registration scope","messagePattern":"Invalid Discord command registration scope","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/chat-discord-command-registration.ts","lineNumber":158,"sourceCode":"  return createHash(\"sha256\")\n    .update(\n      JSON.stringify(\n        priorCloseCopy\n          ? priorCloseCopyDefinition(id)\n          : discordPaperclipCommandDefinition(id),\n      ),\n    )\n    .digest(\"hex\");\n}\n\n/** Persist this prepared descriptor before calling reconcile; its CAS must\n * require that durable row. Do not mint a new owner to bypass a conflict. */\nexport function createDiscordCommandRegistration(\n  scope: DiscordCommandRegistrationScope,\n): DiscordCommandRegistration {\n  const parsed = scopeSchema.safeParse(scope);\n  if (!parsed.success)\n    throw new Error(\"Invalid Discord command registration scope\");\n  return freezeState({\n    schema: \"paperclip.discord.command-registration.v1\",\n    scope: parsed.data,\n    ownerId: randomBytes(16).toString(\"hex\"),\n    phase: \"prepared\",\n  });\n}\n\nexport function parseDiscordCommandRegistration(\n  input: unknown,\n  scope: DiscordCommandRegistrationScope,\n  /** Maintenance only; prior attempted writes and arbitrary digests stay closed. */\n  allowKnownPriorDefinition = false,\n): DiscordCommandRegistration | null {\n  const expected = scopeSchema.safeParse(scope);\n  const parsed = stateSchema.safeParse(input);\n  if (!expected.success || !parsed.success) return null;\n  for (const key of Object.keys(","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-discord-command-registration.ts#L140-L176","documentation":"createDiscordCommandRegistration validates its scope against scopeSchema before freezing the registration state. A scope object that is missing required fields or has fields of the wrong shape fails safeParse and throws this Error; no registration row or ownerId is minted.","triggerScenarios":"Calling createDiscordCommandRegistration({}) or with a partially filled scope — e.g. missing applicationId/guildId or ids of the wrong format — so scopeSchema.safeParse returns success:false.","commonSituations":"Config loaded from env where DISCORD_APPLICATION_ID/GUILD_ID are unset; typo'd scope keys (appId vs applicationId); passing the whole Discord client object or a string instead of the scope object.","solutions":["Pass the complete scope object with all fields required by scopeSchema (correct applicationId, guild/scope ids, etc.).","Verify the Discord application/guild config values are loaded (env vars set, not empty).","Validate the scope with the same schema at config-load time to fail fast with a clearer message.","Log the Zod error (parsed.error) from safeParse to see exactly which field failed."],"exampleFix":"// before\ncreateDiscordCommandRegistration({ applicationId: process.env.DISCORD_APP_ID }) // env unset -> throws\n// after\nif (!process.env.DISCORD_APP_ID || !process.env.DISCORD_GUILD_ID) throw new Error(\"set DISCORD_APP_ID and DISCORD_GUILD_ID\");\ncreateDiscordCommandRegistration({ applicationId: process.env.DISCORD_APP_ID, guildId: process.env.DISCORD_GUILD_ID });","handlingStrategy":"validation","validationCode":"const parsed = scopeSchema.safeParse(scope);\nif (!parsed.success) throw new Error('invalid Discord registration scope: ' + parsed.error.issues.map(i => i.path.join('.')).join(','));","typeGuard":"function isValidScope(s) { return typeof s === 'object' && s !== null && typeof s.applicationId === 'string' && s.applicationId.length > 0; } // plus guildId per scopeSchema","tryCatchPattern":"try {\n  const reg = createDiscordCommandRegistration(scope);\n} catch (e) {\n  if (/Invalid Discord command registration scope/.test(e.message)) {\n    failFast('Discord command scope config is incomplete; check applicationId/guildId settings');\n  }\n  throw e;\n}","preventionTips":["Validate Discord scope config (applicationId, guildId) at startup before the reconciler runs.","Fail fast with a clear message when env vars DISCORD_APPLICATION_ID/DISCORD_GUILD_ID are unset.","Use a typed scope constructor so keys can't be typo'd.","Log Zod issue paths when scope validation fails."],"tags":["validation","discord","config","zod","scope"],"backgroundTag":"schema-validation-failed","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}