Closed (fixed)
Project:
Drupal core
Version:
11.5.x-dev
Component:
base system
Priority:
Major
Category:
Task
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
25 Feb 2026 at 10:35 UTC
Updated:
23 Oct 2026 at 10:01 UTC
Jump to comment: Most recent
Comments
Comment #3
berdirPushed the change to an MR.
I did stumble into this again because we're running into issues when our current large update, which installs and uninstalls several modules through update functions, gets killed due to excessive memory. In local testing in ddev without memory limit, I observed up to 666MB (yes, exactly, really). With this change, it did grow to 250-300MB but then suddenly dropped again to < 200MB and never went above 300.
Comment #4
berdirTests are still failing pretty hard, to be investigated.
Comment #5
catchQuite a lot of these:
Comment #6
berdirYes, one problem is the uninstallValidators in ModuleHandler. That isn't being reattached in \Drupal\Core\Extension\ModuleInstaller::updateKernel, so it references the old container. The problem is that accessing it is deprecated:
The "module_installer.uninstall_validators" service is deprecated in drupal:11.1.0 and is removed from drupal:12.0.0. Inject "!tagged_iterator module_install.uninstall_validator" instead. See https://www.drupal.org/node/3432595
Not sure how to solve that :-/
another, more common one is the mime type guesser, a static call that happens through \Drupal\Core\File\MimeType\MimeTypeGuesser::registerWithSymfonyGuesser(), this currently only on preHandle(). I tried moving it to rebuildKernel as well, but didn't fix the test fail yet.
Comment #7
godotislateOff the cuff thought, no idea if actually workable: loop through
uninstallValidatorsand use the reverse container to get their service IDs before the container is rebuilt. (Unless it's already keyed by service ID? That'd be super convenient.)After the container is rebuilt, reconstitute each uninstall validator using their service ID.
Maybe this is something that DependencySerializationTrait can do, and then do something like the
reinjectMe()method like ConfigImporter has.Comment #8
berdir@godotislate: Thanks, that helped. Not sure if what I came up is the best approaach, but it works. At first it didn't, but then I noticed that that failing test was a config importer, so that also hit #3564735: Container / service exceptions while installed from existing config. added the same change here which I came up with separately.
Also, as usual with these changes, there are rabbit holes within rabbit holes. The failing package manager tests took me a while to track down. Noticed that the event dispatcher gets persisted there, which I finally tracked down to \Drupal\Tests\package_manager\Kernel\SandboxManagerBaseTest::register(). That's not ok, because it has injected service locators and other callbacks that keep references to the old container around. Disabled for now, lets see what really fails without that and then we probably want a separate issue to handle that differently, or do it here depending on how big that gets.
Comment #9
berdirStill a ton of test fails here. Lots of additional package tests doing weird stuff with persisted services. Various one-off tests having pseudo-DI properties that become outdated. updating is broken, request stack is empty. Maybe #2613044: Requests are pushed onto the request stack twice, popped once will help with that, maybe not. More likely that the update kernel doesn't do things properly.
Comment #10
andypostthere's few things hardcoded so #2719315: Remove unnecessary system.module path setup in installer and related trying to simplify, maybe it will help
Comment #11
berdirI debugged this a bit, my guess is that this happens in updates when a container rebuild happens, then the controller and injected dependencies are still on the old container.
I honestly don't know if this is feasible like this. Interestingly, when running updates through drush, I didn't have issues like this, I'm not sure how to resolve this. We could try to reinject in Drupal\system\Controller\DbUpdateController::handle() after running the updates.
I wonder if we should resort to a different mechanism to fix the memory issue. Maybe we could could have a soft reset, that only resets non-synthentic services?
Comment #12
alexpottThis change looks like it should result in quite a few changes to \Drupal\Core\DrupalKernel::resetContainer() as that is re attaching synthetic services like the kernel. Don't think it needs to with this change.
Comment #13
berdir> This change looks like it should result in quite a few changes to \Drupal\Core\DrupalKernel::resetContainer() as that is re attaching synthetic services like the kernel. Don't think it needs to with this change.
I don't quite get what you mean with that.
I didn't write a new comment, but I did implement that soft-reset approach that only resets non-synthentic services, which is working a lot better. So yes, with that, we possibly no longer need some of the changes, like the module installer as it would still kind of work, it's still wrong though. Same with the package manager test, I can probably undo that tag, but those tests and how they change the container are really weird.
Comment #14
mark_fullmerIf it's useful for test coverage, I'm cross-referencing #3601236: Drupal web installer crashes with "synthetic service kernel" error when pathauto is enabled. The PathAuto module adopted OOP-based hooks and specifically uses dependency injection in one of the new hook classes. The instantiation of the config_factory service via dependency injection triggered the Symfony exception mentioned above (You have requested a synthetic service ("kernel")).
This is explained in depth at https://www.drupal.org/project/pathauto/issues/3601236#comment-16663842
So perhaps test coverage for this issue should include the use of dependency injection in an OOP hook class.
Comment #15
tlo405 commentedI've been running into this problem on a D11 upgrade... The webform and pathauto modules seem to be the culprit in my case. I did come from the pathauto issue queue and ended up finding this issue. I found some discussions on slack as well regarding this... but sounds like this issue here is the preferred fix? I've found a few other patches in some of these other issues, but it seems like this one is the correct way forward.
I also read that this apparently isn't a problem in 11.4? I'm trying to update to 11.3 (I'm already going from 10.6.x to 11.3.x, so I would prefer not to have to make another jump up to 11.4.x). I don't like to pull in patches to my project that have no chance of ever getting merged, but it seems like this one here is my best bet.
I'll say, the latest MR does work for me, but @berdir it looks like there is still more to be done here? I don't want to move it to RTBC yet if that's the case.
Comment #16
berdirI figured out what caused the test to fail, it was that I didn't reset private services.
It's so hard to follow all this, but I feel like doing this could allow us to simplify and remove some overlapping bits in \Drupal\Core\DrupalKernel::attachSynthetic() and \Drupal\Core\DrupalKernel::resetContainer(), I don't entirely get why they're two different methods and both are called during the installer and the reset only if more than one module is being installed?
Currently, the reset() method only keeps synthetic services. But then there's also the persist_ids parameter and services tagged with that, which is set in resetContainer(). If we'd also respect that directly inside reset() then we wouldn't need that anymore, I think? We still need to reinitialize some services though.
But I think that could go into follow-ups.
Comment #17
tlo405 commentedThis issue is a bit difficult to follow, and based on other Drupal.org issues and Slack discussions, there appear to be several ways to trigger the "You have requested a synthetic service ("kernel"). The DIC does not know how to construct this service" error. That said, I can confirm that the latest merge request resolves the issue for me in my project.
Comment #18
alexpottTests look like they are failing... so this definitely needs work.
Comment #19
berdirMy last cleanup there didn't handle the weird request_stack service correctly (non-synthetic service but must not be reset)
Comment #20
tlo405 commentedI've tested this one out again, looks good to me.
Comment #21
alexpottI left some review comments on the MR.
One thing that's not explained is the move of
MimeTypeGuesser::registerWithSymfonyGuesser($this->container);- looking at this I have two thoughts:Comment #22
berdirI thought I replied to @21 but can't seem to find it anymore.
That call is in the super-critical-path (pre-page-cache-hit). Triggering an event there is not an option.
That said, the reason it's there isn't that it is earlier, it is that rebuilding a container does re-register that, which currently is inconsistent (still on the old container).
Setting back to RTBC as I just accepted some suggestions.
Comment #23
catchI think this means we should add
Drupal\Core\File\MimeType\MimeTypeGuesserto thecore/composer.jsonclassmap entry which is for very early bootstrap classes. That list may be out of date for other reasons, but we could add the one class here and open a follow-up to review it overall?Comment #24
berdirWe have a follow-up: #3612177: Update autoload classmap for Symfony runtime and etc.. I can add the MimeTypeGuesser, will try my patch on core and see what it reports, we are likely missing a lot.
Comment #29
catchLet's just add it in that issue.
Committed/pushed to main, 12.0.x, 11.x and 11.5.x, thanks!
Comment #32
ressaThanks for fixing this, just adding a possibly related issue.