mattermost-community/focalboard · error

cannot upsert notification hint: %w

Error message

cannot upsert notification hint: %w

What it means

notifySubscribers wraps an error from UpsertNotificationHint when persisting the notification hint (subscriber, block, modified-by) to the database fails. The hint mechanism throttles/deduplicates block-change notifications; without a successful upsert the subscriber will not be notified. The root cause (store error) is preserved with %w.

Source

Thrown at server/services/notify/notifysubscriptions/subscriptions_backend.go:173

	}
	return merr.ErrorOrNil()
}

// notifySubscribers triggers a change notification for subscribers by writing a notification hint to the database.
func (b *Backend) notifySubscribers(subs []*model.Subscriber, blockID string, idType model.BlockType, modifiedByID string) error {
	if len(subs) == 0 {
		return nil
	}

	hint := &model.NotificationHint{
		BlockType:    idType,
		BlockID:      blockID,
		ModifiedByID: modifiedByID,
	}

	hint, err := b.appAPI.UpsertNotificationHint(hint, b.getBlockUpdateFreq(idType))
	if err != nil {
		return fmt.Errorf("cannot upsert notification hint: %w", err)
	}
	if err := b.notifier.onNotifyHint(hint); err != nil {
		return err
	}

	return nil
}

// OnMention satisfies the `MentionListener` interface and is called whenever a @mention notification
// is sent. Here we create a subscription for the mentioned user to the card.
func (b *Backend) OnMention(userID string, evt notify.BlockChangeEvent) {
	if evt.Card == nil {
		b.logger.Debug("Cannot subscribe mentioned user to nil card",
			mlog.String("user_id", userID),
			mlog.String("block_id", evt.BlockChanged.ID),
		)
		return
	}

View on GitHub (pinned to a84bbb65e3)

Solutions

  1. Check the wrapped cause from UpsertNotificationHint (DB connectivity, constraint errors)
  2. Verify the notification hints table exists and matches the current schema
  3. Validate that the subscriber record still exists and is valid
  4. Retry the notification — hint writes are idempotent upserts

Example fix

// before
hint, err := b.appAPI.UpsertNotificationHint(hint, freq)
if err != nil {
	return fmt.Errorf("cannot upsert notification hint: %w", err)
}
// after
hint, err := b.appAPI.UpsertNotificationHint(hint, freq)
if err != nil {
	logger.Error("hint upsert failed", "blockID", blockID, "err", err)
	return fmt.Errorf("cannot upsert notification hint: %w", err)
}
Defensive patterns

Strategy: retry

Validate before calling

// verify subscriber exists before a change that will notify
if _, err := appAPI.GetSubscribersForBlock(blockID); err != nil {
	return err
}

Try / catch

err := backend.BlockChanged(evt)
if err != nil && strings.Contains(err.Error(), "cannot upsert notification hint") {
	// transient DB issue; safe to retry the notification path
	return retryBlockNotify(evt)
}

Prevention

When it happens

Trigger: A block change occurs for a subscribed block and the appAPI.UpsertNotificationHint call fails — database unavailable, constraint violation on the hints table, invalid block/subscriber IDs, or the block update frequency config cannot be resolved (unknown block type).

Common situations: Database connection pool exhaustion under heavy editing; schema drift after upgrading Focalboard where the hints table is missing/outdated; orphaned subscriber records pointing at deleted users.

Related errors


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