Skip to content

Disable Message Bundles doesn't fully disable message bundles #4508

Description

@eriksejr

Describe the Bug:
cfg.General.DisableMessageBundles is checked after dedupAlerts() in engine/message/db.go, not before. dedupAlerts() also bundles some alerts, mainly status update notifications. As a result cfg.General.DisableMessageBundles doesn't completely disable message bundles.

Steps to Reproduce:

  1. Disable message bundling globally
  2. Have a number of users receiving status update notifications
  3. View the message log. Bundling of some of these notifications is still going on, due to dedupAlerts() resulting in delayed (sometimes by many hours) delivery of these notifications.

Expected Behavior:
When message bundling is disabled, no messages - status update notification or otherwise - should appear as bundled in the message log and every alert and update notification should be delivered in a timely manner.

Observed Behavior:
When message bundling is disabled, some status update notifications are bundled and delayed.

Application Version:
Output of goalert version and/or version information from view-source on the UI.

$ goalert version Version: v0.34.1-29-gfad95c55c-dirty GitCommit: fad95c55c8a399d988811e2a5ac31d31419a7afc (dirty) BuildDate: 2026-06-05T14:18:56-04:00 GoVersion: go1.26.3-X:nodwarf5 (gc) Platform: linux/amd64 Migration: fix-queue-name (#278)

Desktop:

  • OS: Windows
  • Browser Firefox
  • Version 151.03

Additional Context:
A minor patch to engine/message/db.go seems to resolve this issue by moving the check for cfg.General.DisableMessageBundles before dedup alerts:

diff --git a/engine/message/db.go b/engine/message/db.go
index 6122567e8..be7c497ac 100644
--- a/engine/message/db.go
+++ b/engine/message/db.go
@@ -381,6 +381,14 @@ func (db *DB) currentQueue(ctx context.Context, tx *sql.Tx, now time.Time) (*que
                }
        }

+       // dedupAlerts and bundleAlertMessages both "bundle" alert notifications (collapsing
+       // multiple pending messages and marking the extras with last_status='bundled'). When
+       // message bundles are disabled, neither should run, so each distinct notification is
+       // delivered on its own rather than silently collapsed.
+       if cfg.General.DisableMessageBundles {
+               return newQueue(result, now), nil
+       }
+
        result, err = dedupAlerts(result, func(parentID string, duplicateIDs []string) error {
                _, err = tx.StmtContext(ctx, db.bundleMessages).ExecContext(ctx, parentID, sqlutil.UUIDArray(duplicateIDs))
                if err != nil {
@@ -393,10 +401,6 @@ func (db *DB) currentQueue(ctx context.Context, tx *sql.Tx, now time.Time) (*que
                return nil, fmt.Errorf("dedup alerts: %w", err)
        }

-       if cfg.General.DisableMessageBundles {
-               return newQueue(result, now), nil
-       }
-
        result, err = bundleAlertMessages(result, func(msg Message) (string, error) {
                var userID sql.NullString
                if msg.UserID != "" {

If this is the intended behavior maybe a separate option which disables the "dedup" of status update notifications would resolve this issue without changing the current behavior of the disable bundling setting.

Disclosure: AI was used to assist me in finding this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions