Allow update.php to load when entity type info needs to be updated

Created on 16 April 2024, 9 months ago
Updated 14 June 2024, 7 months ago

Problem/Motivation

It's perfectly valid to remove an entity type from code and you can still remove it from the stored definitions, as was solved here: #2655162: Fatal error when updating or deleting an entity type after removing its class/definition from the codebase

However, if there is any entity reference field that still pointed to the old entity type, you cannot use update.php to fix those fields because the site will crash before you get the chance to run your updates. The Drush command updb works fine.

This is because update.php has to render things, whereas Drush does not, and therefore calls hook_theme() on all modules. When it gets to views_theme(), all Views plugins are loaded, which in turn cascades through views_views_data(), core_field_views_data and eventually winds up in EntityReferenceItem::schema() where the following exception is thrown:

Field '%s' on entity type '%s' references a target entity type '%s' which does not exist.

Steps to reproduce

  1. Create a field on a node that points to a custom entity type
  2. Remove said entity type from code
  3. Visit update.php

Proposed resolution

Limit the hook_theme invocations when using the UpdateKernel to just the system module.
Enforce Claro on the update.php page.

Remaining tasks

Received in 55
Done.

User interface changes

Update.php will now use Claro.

API changes

N/A

Data model changes

N/A

Release notes snippet

N/A

🐛 Bug report
Status

Fixed

Version

10.3

Component
Base 

Last updated 2 days ago

Created by

🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

Live updates comments and jobs are added and updated live.
  • Contributed project blocker

    It denotes an issue that prevents porting of a contributed project to the stable version of Drupal due to missing APIs, regressions, and so on.

Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @kristiaanvandeneynde
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    An example of this crash can be seen here: https://git.drupalcode.org/project/group/-/jobs/1337503#L914

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Here's another WTF caused by Views that I stumbled upon 6 years ago: #2651974-44: field_ui_entity_operation() cannot respect route parameters because of incorrectly named routes

    At this point I'm starting to wonder if we should just take away Views' car keys because it's obviously drunk. It's asking for so much information that, whenever the info it wants hasn't been built yet or is unstable, your system crashes.

    I think the first suggestion in the IS is probably the safest to explore, work with an allowlist rather than the inverse. But if we were going to go with a blocklist, we'd basically end up saying "Views bad" as it would be the only thing on that list and we'd run into the same issue again once another core (or contrib) modules starts asking for a lot of information.

    For posterity, at the time of writing the first suggestion was:

    Limit the hook_theme invocations when using the UpdateKernel to just the bare minimum: system and the active theme for update.php

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    kristiaanvandeneynde changed the visibility of the branch 3441222-trying-to-repair to hidden.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    kristiaanvandeneynde changed the visibility of the branch 3441222-trying-to-repair to active.

  • Status changed to Needs review 9 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    The current MR allows me to at least visit update.php already. Will check if it works properly.

  • Pipeline finished with Failed
    9 months ago
    Total: 130s
    #147951
  • Pipeline finished with Failed
    9 months ago
    Total: 130s
    #147952
  • Pipeline finished with Failed
    9 months ago
    Total: 132s
    #147950
  • Pipeline finished with Failed
    9 months ago
    #147955
  • Pipeline finished with Failed
    9 months ago
    #147961
  • 🇬🇧United Kingdom catch

    The general problem of update.php has been discussed in #2540416: Move update.php back to a front controller and #2250119: Run updates in a full environment .

    The exception was added in 📌 Throw a better exception when a reference field can't find the target entity type Fixed , although to replace a more cryptic exception that existed before, maybe we can change this to log a warning instead?

    🐛 ViewsData should not cache by language Needs work has some discussion about views_field_data() and the beginnings of ideas of making it use value objects (which could then produce the definitions when requested, not every cache rebuild). I feel like register_theme should not exist at this point, looks more suited to Drupal 7 theme functions than twig templates. Modules can define hook_theme() themselves, plugins produce render arrays that can set #theme, what is register_theme actually doing that's useful?

  • Pipeline finished with Failed
    9 months ago
    Total: 990s
    #148058
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Re #8 I am fully onboard with your idea about making Views do less and make it smarter for the things it still does do.

    I'd keep the exception rather than a warning because these fields should fail loudly if their schema has invalid pieces. But we need to be able to make the schema valid again, which is currently not possible without my MR or drush updb

    Regarding the changes to update.php: It's actually helpful to have a separate kernel for update.php as I could use that to make this MR work.

  • Pipeline finished with Success
    9 months ago
    Total: 987s
    #148207
  • Pipeline finished with Failed
    8 months ago
    Total: 368s
    #155483
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    This seems to be fully functional now. I added a new setting that you can use to either allow more modules than just system or simply allow ALL modules (old behavior).

    Probably needs proper dependency injection for the kernel and settings services.

  • Pipeline finished with Failed
    8 months ago
    #155498
  • Pipeline finished with Failed
    8 months ago
    Total: 328s
    #155522
  • Pipeline finished with Failed
    8 months ago
    Total: 342s
    #155540
  • Pipeline finished with Running
    8 months ago
    #155549
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Seeing some random unrelated test fails

  • Status changed to Needs work 8 months ago
  • 🇺🇸United States smustgrave

    Believe the unit failure will be fixed by a rebase.

  • Pipeline finished with Failed
    8 months ago
    #159479
  • Status changed to Needs review 8 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Still has the random failure and the sniffer failure relating to a mismatching DB version, but many people are reporting that one on Slack. Any idea regarding the random failure?

  • 🇺🇸United States nicxvan

    It's not a random failure, it's because you changed the default.settings.php

    1) Drupal\Tests\ComposerIntegrationTest::testExpectedScaffoldFiles with data set #18 ('sites/default/default.settings.php', 'assets/scaffold/files/default...gs.php')
    Scaffold source and destination files must have the same contents.
    Failed asserting that two strings are equal.
    --- Expected
    +++ Actual
    @@ @@
    $settings['update_free_access'] = FALSE;\n
    \n
    /**\n
    - * Limits the modules to build the theme registry for on update.php.\n
    - *\n
    - * Because update.php needs to render things, the theme registry is built. Some\n
    - * modules such as Views need to load a lot of data to build this registry and\n
    - * some of that data may be unstable until the updates are ran. By default, the\n
    - * list of modules is reduced to just system, but you can add to this list or\n
    - * set the setting to FALSE to have all modules loaded.\n
    - */\n
    -# $settings['update_theme_registry_module_filter'] = ['system'];\n
    -\n
    -/**\n
    * Fallback to HTTP for Update Manager and for fetching security advisories.\n
    *\n
    * If your site fails to connect to updates.drupal.org over HTTPS (either when\n

  • 🇺🇸United States nicxvan

    I reviewed this: https://git.drupalcode.org/project/drupal/-/merge_requests/4860/diffs

    I updated default.settings.php with the same changes and the tests are passing locally.

  • Pipeline finished with Success
    8 months ago
    Total: 1047s
    #162096
  • Status changed to Needs work 8 months ago
  • 🇺🇸United States nicxvan

    Looks good to me, tests are passing now.

    I ran test only as well and that fails as expected.

    I did have one question, why don't you need to call $this->build(); again after the cache delete with the full module list?

  • Status changed to RTBC 8 months ago
  • 🇺🇸United States nicxvan

    Never mind I realized why I think. It's because it's only on update.php the next page load will hit the else.

    Also it would defeat the purpose of this change.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    I did have one question, why don't you need to call $this->build(); again after the cache delete with the full module list?

    We don't cache the full result in the "light version". So next time someone requests the registry, it will be calculated anew. If that happens outside of the update page, then it will be with all modules and that result will be cached.

    Thanks for the review and the fix, I completely overlooked that one. Only thing I can see now that might be holding this back is that we're not injecting 'settings' and 'kernel' via DI.

  • Status changed to Needs work 8 months ago
  • 🇳🇿New Zealand quietone

    The title here is a statement of the problem, it would be better to describe what is being fixed. I am tired or I would make a suggestion. The proposed resolution here is a list of options so I didn't look a the code. I did leave some comments on the MR about improving the comments.

    And why not use DI as mentioned in the previous comment.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Yeah didn't expect this to get set to RTBC without the DI being sorted out :) Currently a bit stretched for time, but will try to prioritize this when I do get some contrib/core time. Thanks for the reviews!

  • 🇬🇧United Kingdom catch

    Had a go at a re-title.

  • Pipeline finished with Running
    8 months ago
    #162604
  • Status changed to Needs review 8 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Tried to squeeze this in between other tasks. Hopefully the docs are better now. Took care of DI and changed the logic slightly as suggested by @alexpott

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    I'm guessing this needs a change record for the new setting?

    But the real question is, does the deprecation have to point to that CR or the issue here? If all the CR focuses on is the new parameter, then it's kind of moot to point to that CR for new constructor arguments.

  • Pipeline finished with Failed
    8 months ago
    Total: 543s
    #162647
  • 🇺🇸United States nicxvan

    Sorry about the premature rtbc. My understanding is you link to the CR, the CR has a link back to the issue if there are additional questions.

    Also you can add helpful details to the CR.

  • Pipeline finished with Failed
    8 months ago
    Total: 499s
    #163242
  • Pipeline finished with Success
    8 months ago
    Total: 504s
    #163273
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    All green now, just need some guidance on #23

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Asked around on Slack and turns out we don't need two CRs, so I added one here: https://www.drupal.org/node/3445054

    Will update the code to point to it.

  • Pipeline finished with Success
    8 months ago
    Total: 661s
    #163368
  • 🇺🇸United States nicxvan

    Thanks! I also just want to make it clear, this probably wants to make it into a recommended release before Drupal 10.3 drops since that introduces the upstream change.

  • 🇺🇸United States nicxvan

    Took a pass at the CR.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Good changes IMO, thanks.

  • Status changed to Needs work 8 months ago
  • 🇺🇸United States smustgrave

    Title seems fine now so removing that tag

    left 2 nitpicky stuff on MR but moving to NW if we can get 2 MRs now
    1 for 11.x with deprecations removed
    1 for 10.3 with deprecations still there (current MR).

    Reason being we already did most removals for 11 of deprecated code so can commit to 11 with removals.

  • Pipeline finished with Failed
    8 months ago
    #171604
  • Pipeline finished with Failed
    8 months ago
    Total: 652s
    #171605
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    kristiaanvandeneynde changed the visibility of the branch 10.3.x to hidden.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    kristiaanvandeneynde changed the visibility of the branch 3441222-11-without-deprecations to hidden.

  • Pipeline finished with Failed
    8 months ago
    Total: 682s
    #171608
  • Pipeline finished with Failed
    8 months ago
    Total: 718s
    #171607
  • Merge request !805010.3. version with deprecations → (Open) created by kristiaanvandeneynde
  • Pipeline finished with Failed
    8 months ago
    Total: 352s
    #171624
  • Pipeline finished with Canceled
    8 months ago
    #171630
  • Pipeline finished with Canceled
    8 months ago
    Total: 158s
    #171634
  • Pipeline finished with Canceled
    8 months ago
    Total: 81s
    #171637
  • Pipeline finished with Canceled
    8 months ago
    Total: 365s
    #171631
  • Status changed to Needs review 8 months ago
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Think we have a D11 and D10.3 ready MR now. Changed the order of the optional params so that the deprecation would be nicer for D11 where the optional param was still last.

  • Pipeline finished with Success
    8 months ago
    Total: 630s
    #171638
  • Pipeline finished with Failed
    8 months ago
    #171639
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Test fails in the D11 version seem completely unrelated, as if HEAD is broken

  • Pipeline finished with Success
    8 months ago
    Total: 1271s
    #171672
  • 🇺🇸United States smustgrave

    Ran the test-only job for the 11.x branch, won't post the entire output but can viewed here https://git.drupalcode.org/issue/drupal-3441222/-/jobs/1584320

    Coverage appears to be there.

    Reviewed the change record and adequately describes the issue that the new settings is overcoming, least to me.

    Deprecations in 10.3 appear good to me as well with removals in the 11.x MR.

    Believe this one is good +1 from me.

  • Status changed to RTBC 8 months ago
  • 🇺🇸United States nicxvan

    Looks good to me too.

    It seems that @quietone's concerns about the comments have been addressed as well as they both read clearer.

  • 🇬🇧United Kingdom catch

    Don't have time to commit this today (or probably this week - about to head afk for at least a couple of days), but +1 from me.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Thanks for the many reviews, much appreciated.

  • 🇬🇧United Kingdom catch

    Discussed this briefly with @alexpott and he wondered what happens with this MR if you have gin + gin_toolbar installed - i.e. does gin work fine on update.php without gin_toolbar's stuff?

  • Status changed to Needs review 7 months ago
  • 🇬🇧United Kingdom catch
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    I just tried this by setting Gin as the admin theme and it does not seem to style update.php at all.

  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    That's because you don't have

    $settings['maintenance_theme'] = 'gin';
    

    in your settings.php. This works due to \Drupal\system\Theme\DbUpdateNegotiator::determineActiveTheme()

    I think this unfortunately adds a layer of complexity on top of this change. We have some options:

    1. Only allow this if the active theme has no module dependencies (this would work for gin fwiw as it has no module dependencies)
    2. Error if the active theme has module dependencies
    3. Add the active theme's module dependencies

    I think 2 or 3 are best. I started preferring 3 but actually I think I prefer 2 - I don't think we should allow maintenance themes that require modules. But maybe a frontend maintainer would disagree.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    I tend to agree with 2 as 3 would put us right back at square one if one of these dependencies turns out to be unstable.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Pushed a change to the 11.x branch to see what tests have to say.

    This does lead to a minor contradiction in a sense that we're introducing a setting that allows you to choose which modules are active on update.php, but then immediately ban you from using any theme that depends on a module. Why even offer the choice at that point?

    I'm wondering if we shouldn't just hard-code the module limit to 'system' then instead of providing a setting that allows you to choose which modules remain active. Although that would obviously be a BC break.

  • Pipeline finished with Failed
    7 months ago
    Total: 699s
    #177828
  • Pipeline finished with Success
    7 months ago
    Total: 574s
    #177855
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    P.S.: Once there is a consensus, I will update the 10.3 branch also.

  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    I feel that only allowing core and system theming in update.php is fine. Maybe a BC break is what is needed here. Maybe we limit to system. Have no new settings at all. If a theme depends on a module it not a good candidate for update.php anyway so instead of the exception we should check this in \Drupal\system\Theme\DbUpdateNegotiator and fallback to claro if the theme has dependencies. And then we are done. It's super rare that a module returns themed output from it's update function anyway.

  • Pipeline finished with Canceled
    7 months ago
    Total: 21s
    #178027
  • Pipeline finished with Failed
    7 months ago
    Total: 576s
    #178028
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Done, also updated the CR.

  • Pipeline finished with Canceled
    7 months ago
    Total: 407s
    #178043
  • Pipeline finished with Success
    7 months ago
    Total: 584s
    #178063
  • Pipeline finished with Failed
    7 months ago
    Total: 1740s
    #178062
  • 🇺🇸United States nicxvan

    I think if the plan is to be consistent and only allow the system module, I'm curious why not enforce the same thing on the theme side and only allow Claro?

    It's not a particularly strong opinion, but if this is trying to make updates more stable, custom themes are a place where people many times have hidden dependencies. I know most people don't add module dependencies to their themes and keep that up to date.
    Would that possibly add instability if the theme is calling modules that are not loaded?

    There is nothing preventing a custom theme from having a theme hook that calls field schema too which would cause the same issue that views is causing.

    If you keep the theme negotiation rather than just setting Claro for the update screen, then I think we would need a test where the theme is set with a dependency and we check that update is setting Claro, I don't see a test for that at the moment unless I'm missing it.

  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Re #49 hard-coding Claro for update.php wouldn't necessarily be a bad thing either. We're actually lying right now by saying update.php's theme cannot be changed:

    /**
     * A custom theme for the offline page:
     *
     * ...
     *
     * Note: This setting does not apply to installation and update pages.
     */
    # $settings['maintenance_theme'] = 'claro';
    

    History of the setting applying to update.php:

    1. #2250119: Run updates in a full environment
    2. #3279640: Standard install profile uses Olivero for update.php
    3. #3304285: Remove Seven from core

    Where 1. basically converted the old drupal_maintenance_theme() calls to checking the setting, even though the setting says it does not apply to update.php

    The amount of affected sites might go up, though. Then again, it's quite reasonable to argue update.php should be as stable and minimalistic as possible because your website is unstable when you visit it.

  • 🇬🇧United Kingdom alexpott 🇪🇺🌍

    Yeah I think I agree with @nicxvan - the only real reason to theme this page is if you are trying to brand some white label site builder and there is no branding on the claro version so I think this is fine and way way safer. Claro is not exactly the lightest theme but it is at least tested doing updates on every Drupal test run. I think we might need consensus from product managers to remove this capability.

  • 🇺🇸United States nicxvan

    Adding tag per 51.

    As mentioned in slack, as a developer I'd support using stark on update.php, but that may be more extreme than needed.

    Claro is definitely safer than trying to negotiate themes in the update page load.

  • 🇺🇸United States nicxvan
  • 🇺🇸United States nicxvan
  • 🇫🇮Finland lauriii Finland

    I can see there being some valid cases for this but I don't see how they could be common enough to justify the complexity involved in supporting custom theming for the update.php. Also, the fact that maintenance_theme applies to update.php has been a surprise at least to me in the past because I expected it to only impact the maintenance page which is displayed for users.

  • 🇺🇸United States nicxvan
  • Assigned to nicxvan
  • 🇺🇸United States nicxvan

    I'll update the MRs

  • Issue was unassigned.
  • 🇺🇸United States nicxvan

    Ok both MRs are ready for review, I updated the CR again.

  • Pipeline finished with Success
    7 months ago
    Total: 633s
    #178491
  • Pipeline finished with Failed
    7 months ago
    Total: 878s
    #178493
  • 🇺🇸United States nicxvan
  • Pipeline finished with Success
    7 months ago
    Total: 555s
    #178517
  • 🇧🇪Belgium kristiaanvandeneynde Antwerp, Belgium

    Updated comment to stay below 80 character limit and renamed the CR so that the title reflects the changes properly. Looks great to me now, if I hadn't been so involved myself I'd RTBC.

  • Pipeline finished with Success
    7 months ago
    Total: 582s
    #178989
  • Pipeline finished with Success
    7 months ago
    Total: 552s
    #178993
  • Status changed to RTBC 7 months ago
  • 🇺🇸United States nicxvan
    • catch committed c9160852 on 10.3.x
      Issue #3441222 by kristiaanvandeneynde, nicxvan, catch, alexpott,...
    • catch committed 2477c009 on 10.4.x
      Issue #3441222 by kristiaanvandeneynde, nicxvan, catch, alexpott,...
    • catch committed e0b89916 on 11.0.x
      Issue #3441222 by kristiaanvandeneynde, nicxvan, catch, alexpott,...
    • catch committed 645c4957 on 11.x
      Issue #3441222 by kristiaanvandeneynde, nicxvan, catch, alexpott,...
  • Status changed to Fixed 7 months ago
  • 🇬🇧United Kingdom catch

    Reviewed this again.

    Forcing Claro on update.php is good, we want as consistent an environment as possible and this is not like maintenance mode at all.

    Restricting the theme hooks run should be fine because there are not really customisation points for update.php (and we would not want them to be), having to clear the cache afterwards is a bit of a workaround, but we can't use a null cache or similar here because that could make things even worse - we want as little theme logic running here as possible, not more.

    I've added this to the 10.3.0-rc1 release notes doc.

    Committed/pushed to 11.x/10.4.x and cherry-picked to 11.0.x and 10.3.x respectively, thanks!

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024