Skip to content

Redis tag-index pipeline fallback removes indices for live cache entries #41529

Open

Description

@mattmacrocket

Preconditions and environment

  • magento/magento2 2.4-develop at commit 4962c46d932c2b69989f4fafbe0157739ba781a7.
  • PHP 8.5.9, Redis 8.10.0, Predis 3.7.0 (satisfies the upstream ^3.5 requirement), Symfony Cache 7.4.17.
  • Isolated PHPUnit test of the upstream RedisTagAdapter source with a real RedisAdapter and disposable Redis instance. This was not a full Magento storefront test.
  • The Redis ACL user was created with ACL SETUSER repro on nopass ~* +@all -eval -evalsha -script. Authenticating as repro makes pruneTagIndex() take its documented pipeline fallback. The same Redis instance permits scripts for the control run.

Steps to reproduce

  1. Save a cache item with ID entry and value old, then call RedisTagAdapter::onSave('entry', ['TAG']). Confirm getIdsMatchingAnyTags(['TAG']) contains entry.
  2. Begin deleteByIds(['entry']). In the deleteItems() call, delete the old cache value, then use a second Redis client to save a new value under the same ID and call onSave('entry', ['TAG']) before the original deleteItems() returns true. This controls the concurrent re-save interleaving without relying on timing.
  3. Let deleteByIds() complete and read both the cache item and tag index.

There is a second failure path: make deleteItems() return false while leaving the original item in place, then call deleteByIds(['entry']) and read the item and tag index.

Expected result

Whenever entry still has a stored cache value, it remains in the TAG set, its reverse index, and cache:all_ids. getIdsMatchingAnyTags(['TAG']) should return entry.

Actual result

In both paths, the cache value remains readable, but getIdsMatchingAnyTags(['TAG']) returns an empty array. Direct checks show that membership in the tag set, reverse index, and cache:all_ids is 0 in each case. Later tag-based invalidation can miss this live entry.

The two PHPUnit cases fail on the index snapshot with the script-denied ACL user (2 tests, 18 assertions, 2 failures). They both pass against the same Redis instance when scripts are allowed (2 tests, 18 assertions).

Additional information

deleteByIds() calls pruneTagIndex() even if deletion fails. The pipeline fallback removes index entries without checking whether the data key still exists. The atomic script has a data-existence guard.

This is distinct from #41004, where reverse-index keys remained after the cache data was deleted. Here the cache data remains but its index is removed. I have not reproduced this against Redis Cluster or a full installed Magento storefront.

Release note

No response

Triage and priority

  • Severity: S0 - Affects critical data or functionality and leaves users without workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.

Activity

  1. m2-assistant commented on Oct 12, 2026

    @m2-assistant

    Hi @mattmacrocket. Thank you for your report.
    To speed up processing of this issue, make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce.


    Join Magento Community Engineering Slack and ask your questions in #github channel.
    ⚠️ According to the Magento Contribution requirements, all issues must go through the Community Contributions Triage process. Community Contributions Triage is a public meeting.
    🕙 You can find the schedule on the Magento Community Calendar page.
    📞 The triage of issues happens in the queue order. If you want to speed up the delivery of your contribution, join the Community Contributions Triage session to discuss the appropriate ticket.

  2. github-jira-sync-bot commented on Oct 12, 2026

    @github-jira-sync-bot

    ✅ Jira issue https://jira.corp.adobe.com/browse/AC-19243 is successfully created for this GitHub issue.

  3. added
    Reported on 2.4.xIndicates original Magento version for the Issue report.
    Triage: Dev.ExperienceIssue related to Developer Experience and needs help with Triage to Confirm or Reject it
    on Oct 13, 2026
  4. bluefairydevelopment commented on Oct 27, 2026

    @bluefairydevelopment

    Reproduced on 2.4-develop with Redis 7.0.15 and an ACL user that may not run scripts. After a prune of an id whose value still exists, the value is readable but the tag lookup no longer finds it. With scripts allowed, it does. Fix and tests are in #41719: the pipelined fallback now checks that the data key is gone before pruning, like the Lua script.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue: ready for confirmationReported on 2.4.xIndicates original Magento version for the Issue report.Triage: Dev.ExperienceIssue related to Developer Experience and needs help with Triage to Confirm or Reject it

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions