mattermost-community/focalboard · error
cannot find user: %w
Error message
cannot find user: %w
What it means
getDirectChannelID returns this error when GetUserByID fails while resolving a 'user'-type subscriber's direct channel for subscription delivery. The subscriber's user record cannot be fetched from the Mattermost plugin API, so no DM channel can be opened. The underlying error is wrapped with %w and propagates to SubscriptionDeliverSlackAttachments.
Source
Thrown at server/services/notify/plugindelivery/subscription_deliver.go:53
}
post := &mm_model.Post{
UserId: pd.botID,
ChannelId: channelID,
}
mm_model.ParseSlackAttachment(post, attachments)
_, err = pd.api.CreatePost(post)
return err
}
func (pd *PluginDelivery) getDirectChannelID(teamID string, subscriberID string, subscriberType model.SubscriberType, botID string) (string, error) {
switch subscriberType {
case model.SubTypeUser:
user, err := pd.api.GetUserByID(subscriberID)
if err != nil {
return "", fmt.Errorf("cannot find user: %w", err)
}
channel, err := pd.getDirectChannel(teamID, user.Id, botID)
if err != nil || channel == nil {
return "", fmt.Errorf("cannot get direct channel: %w", err)
}
return channel.Id, nil
case model.SubTypeChannel:
return subscriberID, nil
default:
return "", ErrUnsupportedSubscriberType
}
}
func (pd *PluginDelivery) getDirectChannel(teamID string, userID string, botID string) (*mm_model.Channel, error) {
// first ensure the bot is a member of the team.
_, err := pd.api.CreateMember(teamID, botID)
if err != nil {
return nil, fmt.Errorf("cannot add bot to team %s: %w", teamID, err)View on GitHub (pinned to a84bbb65e3)
Solutions
- Verify the subscriber user exists and is active via GetUserByID
- Prune subscriptions whose users no longer exist
- Check plugin API health and bot permissions
- Handle the wrapped not-found cause gracefully (skip delivery) as done for channel-member checks
Example fix
// before
user, err := pd.api.GetUserByID(subscriberID)
if err != nil {
return "", fmt.Errorf("cannot find user: %w", err)
}
// after
user, err := pd.api.GetUserByID(subscriberID)
if err != nil {
if model.IsErrNotFound(err) {
return "", nil // subscriber deleted; drop silently
}
return "", fmt.Errorf("cannot find user: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
user, err := pd.api.GetUserByID(subscriberID)
if err != nil {
// user gone: remove subscription instead of attempting delivery
_ = removeSubscription(subscriberID)
return
} Type guard
func validUserSubscriber(api UserAPI, id string) bool {
u, err := api.GetUserByID(id)
return err == nil && u.DeleteAt == 0
} Try / catch
err := pd.SubscriptionDeliverSlackAttachments(evt, subscriptionType, subscriberID, extract)
if err != nil {
if model.IsErrNotFound(err) {
return nil // subscriber deleted; skip
}
return err
} Prevention
- Cascade-delete subscriptions when a user account is deleted
- Treat not-found subscriber lookups as skip-and-clean, not hard errors
- Verify user type subscribers are active before opening DM channels
- Check plugin API health before batch notification delivery
When it happens
Trigger: SubscriptionDeliverSlackAttachments processes a subscriber with model.SubTypeUser and GetUserByID(subscriberID) fails — deleted or deactivated subscriber, stale subscription record, plugin API error, or invalid user ID.
Common situations: Subscriptions left behind after user deletion; SSO/LDAP deprovisioning removing users that still have board subscriptions; plugin API outages during notification bursts; instance restores with inconsistent user data.
Related errors
- cannot fetch channel member for user %s: %w
- cannot notify block subscribers for block %s: %w
- cannot find user: %w
- cannot get direct channel: %w
- block fields size limit exceeded
AI-assisted analysis of mattermost-community/focalboard@a84bbb65e3 (2026-08-30).
Data as JSON: /api/errors/659f75cd99d02aee.
Report an issue: GitHub.