mattermost-community/focalboard · info

mention not permitted

Error message

mention not permitted

What it means

ErrMentionPermission is the notifyMentions backend's sentinel for a mention that policy does not allow to be delivered. deliverMentionNotification returns it when the modifying user is unknown, is a viewer, or lacks permission to mention the target (non-team member on open boards, non-board member on private boards). BlockChanged intentionally logs and swallows it as a normal, expected outcome rather than an error.

Source

Thrown at server/services/notify/notifymentions/mentions_backend.go:24

import (
	"errors"
	"fmt"
	"sync"

	"github.com/mattermost/focalboard/server/model"
	"github.com/mattermost/focalboard/server/services/notify"
	"github.com/mattermost/focalboard/server/services/permissions"
	"github.com/wiggin77/merror"

	"github.com/mattermost/mattermost/server/public/shared/mlog"
)

const (
	backendName = "notifyMentions"
)

var (
	ErrMentionPermission = errors.New("mention not permitted")
)

type MentionListener interface {
	OnMention(userID string, evt notify.BlockChangeEvent)
}

type BackendParams struct {
	AppAPI      AppAPI
	Permissions permissions.PermissionsService
	Delivery    MentionDelivery
	Logger      mlog.LoggerIFace
}

// Backend provides the notification backend for @mentions.
type Backend struct {
	appAPI      AppAPI
	permissions permissions.PermissionsService
	delivery    MentionDelivery

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Ensure the mentioning user has the required role (at least commenter/editor on open boards; board membership for guests/private boards).
  2. Only mention users who are team members (open boards) or board members (private boards).
  3. Treat the error as informational: use errors.Is(err, ErrMentionPermission) to log-and-continue exactly as BlockChanged does.
  4. Include valid ModifiedBy user data in the BlockChangeEvent; nil ModifiedBy always yields this error.

Example fix

// before: treating every delivery failure as fatal
if err := backend.BlockChanged(evt); err != nil { return err }
// after
if err := backend.BlockChanged(evt); err != nil && !errors.Is(err, notifymentions.ErrMentionPermission) {
    return err
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before triggering notification, verify modifier and target
if evt.ModifiedBy == nil {
    return // no valid modifier: mention cannot be permitted
}
hasView, _ := permissions.HasPermissionToBoard(mentionedUser.Id, evt.Board.ID, model.PermissionViewBoard)
if evt.Board.Type != model.BoardTypeOpen && !hasView {
    return // would be rejected with ErrMentionPermission
}

Type guard

func canMention(modifier *model.User, board *model.Board) bool {
    return modifier != nil &&
        !modifier.SchemeViewer
}

Try / catch

_, err := backend.BlockChanged(evt) // via BlockChanged flow
if errors.Is(err, ErrMentionPermission) {
    logger.Debug("mention not permitted; skipping", "user", username)
    return nil // expected condition, not a failure
}

Prevention

When it happens

Trigger: A block change contains an @username mention where: evt.ModifiedBy is nil; the modifier is a board viewer; an open-board editor/admin mentions a user who cannot view the team; or any board member mentions a user without PermissionViewBoard on a private board.

Common situations: Guests typing @mentions of users outside their board, viewers attempting mentions, mentions of deactivated/external users, and plugin tests simulating mention events with incomplete ModifiedBy data.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


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