Viewfield formatter cache contexts missing user role context causing content to disappear for anonymous users

Created on 21 August 2025, about 2 months ago

Problem/Motivation

*THEORY* The viewfield formatter does not properly set cache contexts for user roles, causing cached content to be inappropriately shared between anonymous and authenticated users. This specifically manifests as viewfield content disappearing for anonymous users while remaining visible for authenticated users.

Steps to reproduce

I am not able to reliably (due to needing cache invalidation) reproduce but general steps would be

1. Create a view and add it to a viewfield on a page
2. Clear site cache
3. Have an anonymous user visit the page - viewfield content displays correctly (Maybe something like #3078940 ??)
4. Wait for cache to expire or be invalidated (through node updates, cron, etc.)
5. Have an authenticated user visit the page before any anonymous users
6. Anonymous users now see empty viewfield content, while authenticated users continue to see the content

Proposed resolution

Add explicit user role cache contexts to the viewfield formatter to ensure proper cache separation between anonymous and authenticated users.

The fix adds `user.roles:anonymous` cache context to the cache metadata in the `viewElements()` method of `ViewfieldFormatterDefault.php`.

Remaining tasks

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Active

Component

Code

Created by

πŸ‡ΊπŸ‡ΈUnited States NicholasS

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @NicholasS
  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    Before making this issue I reviewed past issues and found some similar reported events, all of which seems could not be re-produced. (see related)

  • Pipeline finished with Failed
    about 2 months ago
    Total: 193s
    #578515
  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    So I think I found two issues which this MR attempts to solve, the per user role cache contexts, and also some not great empty check logic. And I got the if !Element::isEmpty($content) from how some core modules such as core/modules/block/src/BlockViewBuilder.php

    I validated some of this locally after testing.
    - Anonymous users get cache entries with [user.permissions]=a1ad909ca5c5...
    - Admin users get cache entries with [user.permissions]=is-admin
    - Each user role gets its own properly isolated cache bucket
    - No more cache collision between user types

  • πŸ‡ΊπŸ‡ΈUnited States NicholasS
  • Pipeline finished with Success
    about 2 months ago
    Total: 281s
    #578524
  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    More background since I was never able to reproduce. Were on Acquia, with varnish/memcache on core 10.5.1 with paragraphs that have a view ref field, adding no amount of ?query params to the page made the view get restored. Only thing that ever worked was editing the page or clearing caches. We use uptimerobot to monitor the view for a few days but I couldn't find a correlation in the time between incidents, also no obvious events (like draft nodes/unpublish content from the view etc) or traffic (look for weird query params etc) seems to trigger the view to go empty.

    Duration Between Incidents:
    Aug 18, 06:43 β†’ Aug 18, 11:46: ~5 hours
    Aug 18, 11:46 β†’ Aug 19, 15:12: ~27.5 hours
    Aug 19, 15:12 β†’ Aug 20, 14:30: ~23.5 hours

  • πŸ‡ΊπŸ‡ΈUnited States danflanagan8 St. Louis, US

    I don't it makes sense to add a hardcoded cache context since not all Views depend on that cache context.

    Rather, it looks like the cacheability of the View is not carefully handled in the formatter. The newer ViewfieldFormatterRenderedEntities formatter handles cacheability more strictly, I think.

            // Collect cacheability of the view.
            $view_cacheability = $view->getDisplay()
              ->calculateCacheMetadata()
              ->addCacheTags($view->getCacheTags());
            $view_cacheability->applyTo($elements);
    

    https://git.drupalcode.org/project/viewfield/-/blob/8.x-3.x/src/Plugin/F...

    In the default formatter, however, we're calculating cacheability differently, and I suspect it misses things like the access plugin and contextual filters.

            // Get cache metadata from view and merge.
            $view_cacheability = CacheableMetadata::createFromRenderArray($view->element);
            $cacheability = $cacheability->merge($view_cacheability);
    

    This is mostly speculative though at this point.It would be great to write a test to expose the bug.

  • πŸ‡ΊπŸ‡ΈUnited States NicholasS
  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    So any ideas on any what kind of data I can get off prod to help debug if/when this happens again? I tried the database but its seems Acquia dumps the cache tables automatically so I wasn't able to inspect the cache the latest time it disappeared.

    Today I am going to try to remove the exposed filters to see if that helps or not.

  • Pipeline finished with Success
    about 2 months ago
    Total: 171s
    #578554
  • πŸ‡ΊπŸ‡ΈUnited States danflanagan8 St. Louis, US

    Re: debugging, you'd probably want to do that locally. I'd check out this article and see if it helps you approach the problem: https://mglaman.dev/blog/debugging-your-render-cacheable-metadata-drupal

  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    Update: Removing the exposed filter made no diff, it disappeared on me again. So Resorted to turning caching completely off for the view as a temp work around to see if that does the trick over time.

  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    Update: Removing the view cache still did not help, the view disappeared again, so I guess I am going to try out this patch to see if it helps.

  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    Fixed issue headline to be more accurate

  • Pipeline finished with Success
    about 1 month ago
    Total: 186s
    #588083
  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    So to report back the patch did not help. We setup hourly automated cypress tests to test all of our 83 pages that use paragraphs that have viewfields. And after this patch we still had one disappear on us. For some reason its only a few that keep going out on us, but longer we let the cache sit the more go empty, over night I think we got up to 4 empty views.

    Going to try the "always build output: yes" formatter setting to see if that helps.

  • πŸ‡ΊπŸ‡ΈUnited States NicholasS

    WORKAROUND SOLUTION: The temp fix does seem to be to set the "always build output: yes" for the view fields, this has not caused any to go blank yet. I guess our site will just have to keep that option on for the time being.

Production build 0.71.5 2024