Problem / Motivation

  • SitewideAlertRenderer::build() has three return paths. Two correctly apply CacheableMetadata to the returned render array. The third — taken when no active alerts exist — returns a bare empty array with no cache metadata:
// SitewideAlertRenderer::build() line 64–66
if (!$this->sitewideAlertManager->activeSitewideAlerts()) {
    return [];
}
  • Compare with the correctly handled permission-denied path immediately above it:
$build = [];
$cacheMetadata->applyTo($build);
return $build;
  • This creates two distinct problems.

Problem 1: Uncached DB query on every page request when no alerts are active

  • Because the returned [] carries no cache tags or max-age, Drupal's render cache has nothing to store or reuse.
  • On every page render the block calls activeSitewideAlerts(), which executes an entity storage query plus loadMultiple() against the sitewide_alert table.
  • It receives an empty result and returns [] again with no mechanism to avoid repeating this on the next request.
  • Sites with no active alerts — the typical steady state between campaigns — pay this DB query cost on every single page view.

Problem 2: Alerts created after initial page cache warm never appear

  • When an alert is created or enabled, Drupal invalidates the sitewide_alert_list cache tag.
  • Because the cached render array for the no-active-alerts path has no cache tags attached, there is nothing to invalidate.
  • The page continues serving the empty result until the entire cache is manually cleared.

Steps to Reproduce

  • Install sitewide_alert and sitewide_alert_block.
  • Place the Sitewide Alert block on a page.
  • Ensure no sitewide alert entities exist or all are unpublished.
  • Load the page — activeSitewideAlerts() fires an entity query on every request with no render cache short-circuit.
  • Create and publish a new sitewide alert.
  • Load the page again without clearing caches — the alert does not appear.

Proposed Resolution

  • Apply $cacheMetadata to the empty-result return path and add the sitewide_alert_list entity list cache tag so the cache correctly invalidates when an alert is created or enabled:
if (!$this->sitewideAlertManager->activeSitewideAlerts()) {
    $build = [];
    $cacheMetadata
        ->addCacheTags(['sitewide_alert_list'])
        ->applyTo($build);
    return $build;
}
  • The sitewide_alert_list tag is already used by SitewideAlertsController::setCacheTags(['sitewide_alert_list']), confirming it is the correct tag for this entity type's list invalidation.
  • The permission-denied path at lines 54–61 should also add sitewide_alert_list to its $cacheMetadata for the same reason — if a user gains the view published sitewide alert entities permission and an alert exists, their cached permission-denied render array would not invalidate correctly.
Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mglaman created an issue. See original summary.

mglaman’s picture

Version: 3.1.x-dev » 3.0.x-dev

Looks like 3.1.x has this fixed.

mglaman changed the visibility of the branch 3593274-sitewidealertrendererbuild-returns-empty to hidden.

mglaman’s picture

Status: Active » Closed (duplicate)

Looks like it's fixed on 3.0.x but only tagged in 3.1.x. and this is a dupe of #3506754: The "Sitewide Alert" block return an empty array if no alert exists

Patch of the commit for those needing it: https://git.drupalcode.org/project/sitewide_alert/-/commit/0e8f1161a845c...

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.