magento / magento/magento2

Plugin list metadata files generated by setup:di:compile are never used at runtime due to cache ID mismatch

Open
#40,407 9 comments 38 reactions 1 assignee View on GitHub

@koushikch7 is already working on this.

Since Aug 1, 2026.

Area: Framework Component: Frontend Issue: Confirmed Priority: P2 Progress: PR Created Progress: ready for grooming Reported on 2.4.x Reproduced on 2.4.x Triage: Dev.Experience
Dominant language
PHP
Stars
12.2k
Forks
9.4k
PR merge metrics
No merged PRs in 30d

Description

Preconditions and environment

Preconditions and environment:

  • Magento version: 2.4.x (tested on 2.4.7, but affects all versions with pre-compiled plugin metadata)
  • PHP: 8.1+
  • Production mode with setup:di:compile executed
  • Any cache backend (Redis, File, etc.)

Relevant files:

  • vendor/magento/framework/Interception/PluginList/PluginList.php
  • vendor/magento/framework/Interception/PluginListGenerator.php
Steps to reproduce

Steps to reproduce:

  1. Run bin/magento setup:di:compile - this generates plugin metadata files in generated/metadata/

  2. Note the generated plugin-list filenames:
    ls generated/metadata/plugin-list
    Shows: primary|global|plugin-list.php, primary|global|frontend|plugin-list.php, etc.

  3. Run bin/magento cache:flush

  4. Add debug logging to PluginList::_loadScopedData() before $configData = $this->configLoader->load($cacheId):

file_put_contents(BP . '/var/debug.log', "cacheId=$cacheId\n", FILE_APPEND);
  1. Make a frontend request
  2. Check the debug log for the cache IDs being requested at runtime
Expected result

The cache IDs generated at compile-time should match the cache IDs requested at runtime.

Runtime should load the pre-compiled plugin metadata from generated/metadata/*plugin-list.php files, avoiding expensive XML parsing on first request after cache flush.

Expected cache IDs to match:

  • Compile-time file: primary|global|frontend|plugin-list.php
  • Runtime request: primary|global|frontend|plugin-list
Actual result

Actual result:
The cache IDs do NOT match due to different scope ordering logic between compile-time and runtime.

Compile-time (PluginListGenerator::write()) generates:

  • primary|global|plugin-list.php
  • primary|global|frontend|plugin-list.php

Runtime (PluginList::_loadScopedData()) requests:

  • global|primary|plugin-list
  • global|primary|frontend|plugin-list

The order is swapped: primary|global vs global|primary

Root Cause

PluginList::_loadScopedData() contains "move to end" logic (lines 208-218) that reorders scopes:

$index = array_search($scope, $this->_scopePriorityScheme, true);
if ($index !== false) {
    unset($this->_scopePriorityScheme[$index]);
}
$this->_scopePriorityScheme[] = $scope;
$cacheId = implode('|', $this->_scopePriorityScheme) . "|" . $this->_cacheId;

However, PluginListGenerator::write() does NOT have this same logic, so the cache IDs differ.

When scopePriorityScheme starts as ['primary' => 'primary', 'first' => 'global']:

  • Runtime moves 'global' to end → ['primary', 'global'] → primary|global
  • Then moves 'primary' to end → ['global', 'primary'] → global|primary

But compile-time doesn't perform this reordering, resulting in different cache IDs.

Impact

  1. configLoader->load($cacheId) returns empty (file doesn't exist)
  2. Falls through to Redis/file cache (also empty after flush)
  3. Full XML parsing of ALL di.xml files across ALL modules
  4. Pre-compiled metadata files (~600KB+) with 700+ pre-computed plugin inheritance chains are completely wasted
  5. Causes 1-2 second delay on first request after cache:flush
  6. Affects every Magento installation

Suggested Fix

Normalize cache IDs by sorting scopes alphabetically before creating the ID. Apply to both files:

// Before creating cache ID
$sortedScheme = array_values($this->scopePriorityScheme);
sort($sortedScheme);
$cacheId = implode('|', $sortedScheme) . "|" . $this->cacheId;

This ensures cache IDs are deterministic regardless of processing order:

  • ['primary', 'global'] → sorted → ['global', 'primary'] → global|primary|plugin-list
  • ['global', 'primary'] → sorted → ['global', 'primary'] → global|primary|plugin-list
Additional information

No response

Release note

Severity: S2 (Major)

Justification:

  • Affects ALL Magento installations in production mode
  • No workaround without modifying core code
  • 1-2 second delay on every first request after cache:flush
  • Entire feature is broken - the pre-compiled plugin metadata system generates files that are never used
  • Wasted resources - 600KB+ of compiled PHP files are generated during setup:di:compile but completely ignored at runtime
  • Not S1 because the site still functions (just slower)
  • Not S3 because the impact is significant and affects every deployment
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”.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.