{"record":{"id":"830e0da7d3ff7a2a","repo":"paperclipai/paperclip","slug":"invalid-discord-command-owner-identifier","errorCode":null,"errorMessage":"Invalid Discord command owner identifier","messagePattern":"Invalid Discord command owner identifier","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/chat-discord-command-registration.ts","lineNumber":102,"sourceCode":"      retryAfterSeconds?: number;\n    };\n\nfunction freezeState(\n  state: DiscordCommandRegistration,\n): DiscordCommandRegistration {\n  Object.freeze(state.scope);\n  if (state.phase === \"attempted\") {\n    Object.freeze(state.attempt.runtimeFence);\n    Object.freeze(state.attempt);\n  }\n  if (state.phase === \"registered\") Object.freeze(state.receipt);\n  return Object.freeze(state);\n}\n\n/** The public marker is an identifier, never a credential or standalone proof. */\nexport function discordPaperclipCommandDefinition(publicOwnerId: string) {\n  if (!ownerId.safeParse(publicOwnerId).success)\n    throw new Error(\"Invalid Discord command owner identifier\");\n  return {\n    type: 1,\n    name: \"paperclip\",\n    description: `Paperclip session controls [pc:${publicOwnerId}]`,\n    options: [\n      {\n        type: 1,\n        name: \"status\",\n        description: \"Show the current Paperclip task\",\n      },\n      {\n        type: 1,\n        name: \"new\",\n        description: \"Start a new task in a DM or show new-thread guidance\",\n      },\n      {\n        type: 1,\n        name: \"close\",","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-discord-command-registration.ts#L84-L120","documentation":"discordPaperclipCommandDefinition validates the public owner marker with the ownerId Zod schema before building the Discord slash-command payload (type 1 CHAT_INPUT, name 'paperclip'). The marker is an identifier, not a credential; a value failing the schema (wrong shape/charset/length) throws this Error synchronously.","triggerScenarios":"Calling discordPaperclipCommandDefinition with an empty string, undefined/null, or a value containing characters outside the ownerId schema (e.g. spaces, symbols, or overly long ids) instead of the hex/random or schema-conformant owner identifier.","commonSituations":"Passing a Discord user tag like 'user#1234' or display name with spaces; passing a whole JSON blob instead of the id; forgetting to mint the owner via createDiscordCommandRegistration and passing a placeholder like 'me'.","solutions":["Pass a schema-conformant owner id — ideally the ownerId generated by createDiscordCommandRegistration (randomBytes(16) hex).","Log/inspect the value passed in and trim or strip invalid characters (e.g. drop the '#1234' discriminator).","Validate with the same ownerId schema on the caller side before invoking the function.","If migrating stored registrations, re-mint the owner id rather than reusing a legacy non-conforming identifier."],"exampleFix":"// before\nconst def = discordPaperclipCommandDefinition(\"Ada Lovelace#0001\"); // throws\n// after\nconst reg = createDiscordCommandRegistration(scope);\nconst def = discordPaperclipCommandDefinition(reg.ownerId); // hex id","handlingStrategy":"validation","validationCode":"import { ownerId } from './chat-discord-command-registration';\nif (!ownerId.safeParse(publicOwnerId).success) throw new Error('owner id does not match the Discord command ownerId schema');","typeGuard":"function isValidOwnerId(v) { return typeof v === 'string' && /^[0-9a-f]{32}$/.test(v); } // adjust to the actual schema","tryCatchPattern":"let definition;\ntry {\n  definition = discordPaperclipCommandDefinition(publicOwnerId);\n} catch (e) {\n  if (/Invalid Discord command owner identifier/.test(e.message)) {\n    const reg = createDiscordCommandRegistration(scope);\n    definition = discordPaperclipCommandDefinition(reg.ownerId);\n  } else throw e;\n}","preventionTips":["Always mint the owner id via createDiscordCommandRegistration instead of hand-rolling it.","Strip user-facing handles ('name#0001', spaces) before passing identifiers.","Store the hex owner id, never a Discord username or tag.","Validate ids with the shared Zod schema at the boundary."],"tags":["validation","discord","identifier","zod"],"backgroundTag":"invalid-identifier-format","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}