mattermost-community/focalboard · error

invalid subscriber type

Error message

invalid subscriber type

What it means

ErrUnsupportedSubscriberType means a subscription's subscriber type is not one the delivery mechanism can resolve to a destination. getDirectChannelID returns it when the subscriber is not a user/channel type it knows, so plugin delivery cannot determine where to send the notification. It acts as a type guard in the subscription delivery path.

Source

Thrown at server/services/notify/plugindelivery/subscription_deliver.go:16

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.

package plugindelivery

import (
	"errors"
	"fmt"

	"github.com/mattermost/focalboard/server/model"

	mm_model "github.com/mattermost/mattermost/server/public/model"
)

var (
	ErrUnsupportedSubscriberType = errors.New("invalid subscriber type")
)

// SubscriptionDeliverSlashAttachments notifies a user that changes were made to a block they are subscribed to.
func (pd *PluginDelivery) SubscriptionDeliverSlackAttachments(teamID string, subscriberID string, subscriptionType model.SubscriberType,
	attachments []*mm_model.SlackAttachment) error {
	// check subscriber is member of channel
	_, err := pd.api.GetUserByID(subscriberID)
	if err != nil {
		if model.IsErrNotFound(err) {
			// subscriber is not a member of the channel; fail silently.
			return nil
		}
		return fmt.Errorf("cannot fetch channel member for user %s: %w", subscriberID, err)
	}

	channelID, err := pd.getDirectChannelID(teamID, subscriberID, subscriptionType, pd.botID)
	if err != nil {
		return err

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Verify the subscription's SubscriberType is one supported by plugin delivery (channel/user types that map to a Mattermost channel).
  2. Delete or correct the malformed subscription row so notifications target a valid channel.
  3. Align Focalboard plugin and server versions so all subscriber types are understood.
  4. Switch errors.Is(err, ErrUnsupportedSubscriberType) to skip that subscription rather than failing the batch.

Example fix

// before
err := pd.SubscriptionDeliverSlackAttachments(teamID, subID, subscriberType, attachments)
// after
if err := pd.SubscriptionDeliverSlackAttachments(teamID, subID, subscriberType, attachments); err != nil {
    if errors.Is(err, plugindelivery.ErrUnsupportedSubscriberType) {
        return nil // skip unsupported subscription
    }
    return err
}
Defensive patterns

Strategy: type-guard

Validate before calling

switch subscriberType {
case model.SubscriberTypeUser, model.SubscriberTypeChannel:
    // supported
default:
    return fmt.Errorf("unsupported subscriber type %q", subscriberType)
}

Type guard

func isDeliverableSubscriberType(t model.SubscriberType) bool {
    return t == model.SubscriberTypeUser || t == model.SubscriberTypeChannel
}

Try / catch

if err := pd.SubscriptionDeliverSlackAttachments(teamID, subID, subType, attachments); err != nil {
    if errors.Is(err, ErrUnsupportedSubscriberType) {
        return nil // skip: no channel destination for this type
    }
    return err
}

Prevention

When it happens

Trigger: Calling SubscriptionDeliver*/getDirectChannelID with a model.SubscriberType other than the supported kinds (e.g. a bare user type where a channel id is required, or a newly introduced subscriber type not yet handled by the plugin delivery code).

Common situations: Subscriptions persisted by a newer Focalboard version read by older delivery code, custom plugins creating subscription rows with unexpected types, or data corruption in the subscriptions table.

Related errors


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