{"record":{"id":"955d8b4055724ff1","repo":"paperclipai/paperclip","slug":"discord-bot-membership-could-not-be-verified","errorCode":null,"errorMessage":"Discord bot membership could not be verified","messagePattern":"Discord bot membership could not be verified","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/chat-discord.ts","lineNumber":295,"sourceCode":"      `/guilds/${encodeURIComponent(guildId)}/members/${encodeURIComponent(botUserId)}`,\n      \"bot membership lookup\",\n    ),\n    discordJson<DiscordRole[]>(\n      input.fetch,\n      input.botToken,\n      `/guilds/${encodeURIComponent(guildId)}/roles`,\n      \"server roles lookup\",\n    ),\n    discordJson<DiscordChannel[]>(\n      input.fetch,\n      input.botToken,\n      `/guilds/${encodeURIComponent(guildId)}/channels`,\n      \"server channels lookup\",\n    ),\n  ]);\n  const memberId = member.user?.id;\n  if (!memberId || guild.id !== guildId) {\n    throw new Error(\"Discord bot membership could not be verified\");\n  }\n  const memberRoleIds = new Set(member.roles ?? []);\n  const resources: ChatProviderResourceInventoryItem[] = channels\n    .filter((channel) => channel.type === 0 && channel.id)\n    .filter((channel) => {\n      const permissions = channelPermissions({\n        channel,\n        guildId,\n        memberId,\n        memberRoleIds,\n        roles,\n      });\n      return (\n        (permissions & REQUIRED_CHANNEL_PERMISSIONS) ===\n        REQUIRED_CHANNEL_PERMISSIONS\n      );\n    })\n    .sort((left, right) => (left.position ?? 0) - (right.position ?? 0))","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/server/src/services/chat-discord.ts#L277-L313","documentation":"listDiscordBotChannels fetches the guild, the bot's member record (GET /guilds/{guildId}/members/{botUserId}), roles, and channels in parallel. If the member lookup yields no user id, or the returned guild id does not equal the requested guildId, the bot's membership in that server cannot be confirmed and the function throws instead of computing channel permissions against an unverified identity.","triggerScenarios":"listDiscordBotChannels({botUserId, botToken, fetch, guildId}) where GET /guilds/{guildId}/members/{botUserId} returns 404/empty member (member.user?.id falsy), or GET /guilds/{guildId} returns a guild whose id !== guildId.","commonSituations":"Bot was removed from the server after verification but before listing channels; botUserId recorded from a previous verification no longer matches the installed bot; stale cached provider credentials pointing at a different guild; Discord API returning a partial member object due to an expired/limited token.","solutions":["Re-run verifyDiscordBot to refresh the bot identity and confirm the bot is currently installed in the guild","Re-invite the bot to the server if the member lookup fails (bot was kicked or left)","Verify botUserId matches the bot token's user id from /users/@me","Retry after confirming the botToken is valid and has not been regenerated in the Developer Portal"],"exampleFix":"// before: reusing a stale botUserId from an old verification\nawait listDiscordBotChannels({ botUserId: oldBotUserId, botToken, fetch, guildId });\n// after: re-verify first, then use the fresh identity\nconst identity = await verifyDiscordBot({ applicationId, botToken, fetch, guildId });\nawait listDiscordBotChannels({ botUserId: identity.botExternalId, botToken, fetch, guildId });","handlingStrategy":"try-catch","validationCode":"const member = await fetch(`https://discord.com/api/v10/guilds/${guildId}/members/${botUserId}`, { headers: { Authorization: `Bot ${botToken}` } });\nif (!member.ok) throw new Error(`Bot member record missing in guild ${guildId}; re-invite and re-verify`);","typeGuard":null,"tryCatchPattern":"try {\n  await listDiscordBotChannels({ botUserId, botToken, fetch, guildId });\n} catch (err) {\n  if (err instanceof Error && err.message === \"Discord bot membership could not be verified\") {\n    await reverifyAndRetry(guildId);\n  } else throw err;\n}","preventionTips":["Always derive botUserId from a fresh verifyDiscordBot call instead of caching it across sessions","Detect guild member removals (guildDelete / GUILD_MEMBER_REMOVE events) and invalidate stored provider credentials","Handle 401 from the bot token by prompting a token refresh before treating it as a membership problem"],"tags":["discord","integration","api-request","configuration"],"backgroundTag":"resource-not-found","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"}