{"record":{"id":"82d80b2d2eb4763d","repo":"mattermost-community/focalboard","slug":"cannot-upsert-notification-hint-w","errorCode":null,"errorMessage":"cannot upsert notification hint: %w","messagePattern":"cannot upsert notification hint: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/services/notify/notifysubscriptions/subscriptions_backend.go","lineNumber":173,"sourceCode":"\t}\n\treturn merr.ErrorOrNil()\n}\n\n// notifySubscribers triggers a change notification for subscribers by writing a notification hint to the database.\nfunc (b *Backend) notifySubscribers(subs []*model.Subscriber, blockID string, idType model.BlockType, modifiedByID string) error {\n\tif len(subs) == 0 {\n\t\treturn nil\n\t}\n\n\thint := &model.NotificationHint{\n\t\tBlockType:    idType,\n\t\tBlockID:      blockID,\n\t\tModifiedByID: modifiedByID,\n\t}\n\n\thint, err := b.appAPI.UpsertNotificationHint(hint, b.getBlockUpdateFreq(idType))\n\tif err != nil {\n\t\treturn fmt.Errorf(\"cannot upsert notification hint: %w\", err)\n\t}\n\tif err := b.notifier.onNotifyHint(hint); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n\n// OnMention satisfies the `MentionListener` interface and is called whenever a @mention notification\n// is sent. Here we create a subscription for the mentioned user to the card.\nfunc (b *Backend) OnMention(userID string, evt notify.BlockChangeEvent) {\n\tif evt.Card == nil {\n\t\tb.logger.Debug(\"Cannot subscribe mentioned user to nil card\",\n\t\t\tmlog.String(\"user_id\", userID),\n\t\t\tmlog.String(\"block_id\", evt.BlockChanged.ID),\n\t\t)\n\t\treturn\n\t}","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/mattermost-community/focalboard/blob/a84bbb65e32edf972856b329417096ac413518e9/server/services/notify/notifysubscriptions/subscriptions_backend.go#L155-L191","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Check the wrapped cause from UpsertNotificationHint (DB connectivity, constraint errors)","Verify the notification hints table exists and matches the current schema","Validate that the subscriber record still exists and is valid","Retry the notification — hint writes are idempotent upserts"],"exampleFix":"// before\nhint, err := b.appAPI.UpsertNotificationHint(hint, freq)\nif err != nil {\n\treturn fmt.Errorf(\"cannot upsert notification hint: %w\", err)\n}\n// after\nhint, err := b.appAPI.UpsertNotificationHint(hint, freq)\nif err != nil {\n\tlogger.Error(\"hint upsert failed\", \"blockID\", blockID, \"err\", err)\n\treturn fmt.Errorf(\"cannot upsert notification hint: %w\", err)\n}","handlingStrategy":"retry","validationCode":"// verify subscriber exists before a change that will notify\nif _, err := appAPI.GetSubscribersForBlock(blockID); err != nil {\n\treturn err\n}","typeGuard":null,"tryCatchPattern":"err := backend.BlockChanged(evt)\nif err != nil && strings.Contains(err.Error(), \"cannot upsert notification hint\") {\n\t// transient DB issue; safe to retry the notification path\n\treturn retryBlockNotify(evt)\n}","preventionTips":["Ensure the notification hints schema matches the running version after upgrades","Monitor database connection pool saturation during heavy editing","Keep hint upserts idempotent so retries are safe","Alert on persistent UpsertNotificationHint failures — subscribers silently miss notifications"],"tags":["go","notifications","database","upsert"],"backgroundTag":"notification-hint-write-failed","analyzedSha":"a84bbb65e32edf972856b329417096ac413518e9","analyzedAt":"2026-08-30T09:22:20.720Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}