{"record":{"id":"f6d8717cc40f1f22","repo":"mattermost-community/focalboard","slug":"cannot-add-bot-to-team-s-w","errorCode":null,"errorMessage":"cannot add bot to team %s: %w","messagePattern":"cannot add bot to team (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/notify/plugindelivery/subscription_deliver.go","lineNumber":71,"sourceCode":"\t\t\treturn \"\", fmt.Errorf(\"cannot find user: %w\", err)\n\t\t}\n\t\tchannel, err := pd.getDirectChannel(teamID, user.Id, botID)\n\t\tif err != nil || channel == nil {\n\t\t\treturn \"\", fmt.Errorf(\"cannot get direct channel: %w\", err)\n\t\t}\n\t\treturn channel.Id, nil\n\tcase model.SubTypeChannel:\n\t\treturn subscriberID, nil\n\tdefault:\n\t\treturn \"\", ErrUnsupportedSubscriberType\n\t}\n}\n\nfunc (pd *PluginDelivery) getDirectChannel(teamID string, userID string, botID string) (*mm_model.Channel, error) {\n\t// first ensure the bot is a member of the team.\n\t_, err := pd.api.CreateMember(teamID, botID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"cannot add bot to team %s: %w\", teamID, err)\n\t}\n\treturn pd.api.GetDirectChannelOrCreate(userID, botID)\n}\n","sourceCodeStart":53,"sourceCodeEnd":75,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/notify/plugindelivery/subscription_deliver.go#L53-L75","documentation":"getDirectChannel first ensures the delivery bot is a member of the team by calling pd.api.CreateMember(teamID, botID); when that call fails the error is wrapped as 'cannot add bot to team %s'. The subsequent direct channel creation never runs. This is a permission/team-membership failure at the Mattermost API level.","triggerScenarios":"Called from getDirectChannelID (DM subscriptions) or MentionDeliver; pd.api.CreateMember(teamID, botID) returns an error — the bot is already a member but the API errors, the bot is not allowed to join, teamID is invalid, or the bot account is deactivated.","commonSituations":"Bot not invited/configured for the team; bot token lacking 'join_team' permissions; team ID typo or team deleted; Mattermost plugin misconfiguration (bot access token pointing at the wrong bot); Mattermost version differences in CreateMember semantics.","solutions":["Confirm the bot user exists and is active, and that teamID is a valid team ID.","Manually add the bot to the team or grant it the needed permissions so CreateMember succeeds idempotently.","Check the plugin's bot access token configuration in Mattermost system console.","Log/inspect the wrapped cause to distinguish 'already a member' from permission failures."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// before delivery, check bot membership\nbot, err := api.GetUser(botID)\nif err != nil || bot.DeleteAt != 0 {\n\treturn fmt.Errorf(\"bot %s missing or deactivated\", botID)\n}\ntm, _ := api.GetTeamMember(teamID, botID)\nif tm == nil {\n\t_, err = api.CreateMember(teamID, botID) // pre-provision\n\tif err != nil {\n\t\treturn fmt.Errorf(\"pre-provision bot into team %s failed: %w\", teamID, err)\n\t}\n}","typeGuard":null,"tryCatchPattern":"chID, err := deliverer.SubscriptionDeliverSlackAttachments(...)\nif err != nil && strings.Contains(err.Error(), \"cannot add bot to team\") {\n\tlogger.Error(\"bot cannot join team; check bot config/permissions\", \"team\", teamID, \"err\", err)\n\treturn // alert operator rather than retrying blindly\n}","preventionTips":["Provision the bot into required teams during plugin setup instead of at delivery time.","Validate the configured bot access token at startup.","Alert on deactivated/deleted bot accounts."],"tags":["mattermost","plugin","permissions","team-membership"],"backgroundTag":"bot-team-membership-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}