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

  1. Verify the subscriber user exists and is active via GetUserByID
  2. Prune subscriptions whose users no longer exist
  3. Check plugin API health and bot permissions
  4. 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

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


AI-assisted analysis of mattermost-community/focalboard@a84bbb65e3 (2026-08-30). Data as JSON: /api/errors/659f75cd99d02aee. Report an issue: GitHub.