Problem/Motivation

When updating the DB after an update from 8.8.5 to 8.8.1 the following error occurred:

The website encountered an unexpected error. Please try again later.
Drupal\Core\Extension\Exception\UnknownExtensionException: The module mymodule does not exist. in Drupal\Core\Extension\ExtensionList->get() (line 265 of core/lib/Drupal/Core/Extension/ExtensionList.php).

Drupal\Core\Extension\ExtensionList->get('mymodule') (Line: 579)
Drupal\Core\Extension\ExtensionList->checkIncompatibility('chosen') (Line: 318)
update_get_update_list() (Line: 272)
Drupal\system\Controller\DbUpdateController->selection(Object) (Line: 163)
Drupal\system\Controller\DbUpdateController->handle('selection', Object)
call_user_func_array(Array, Array) (Line: 115)
Drupal\Core\Update\UpdateKernel->handleRaw(Object) (Line: 76)
Drupal\Core\Update\UpdateKernel->handle(Object) (Line: 28)
require('/Users/dawehner/Documents/www/drupal/update.php') (Line: 65)

Steps to reproduce:

  1. Install 8.8.1
  2. insert a schema into the key_value which no longer exists: insert into key_value(collection, name, value) values ('system.schema', 'mymodule', 'i:8000;'); I don't know how this ended up there, but it was definitely there on the site
  3. Update the code to 8.8.5
  4. Hit update.php
  5. Sad panda

I did a git bisect which resulted into https://www.drupal.org/project/drupal/issues/2917600

@alexpott Pointed me to a bunch of issues which are out there: https://www.drupal.org/project/drupal/issues/3120910 for example. Applying that patch didn't help.

There's a related but separate bug: if there are orphaned entries in system.schema from modules that are still present in the filesystem but not installed, update.php currently tries to run those updates.

Proposed resolution

Add code to update.inc to better handle orphaned entries in system.schema k/v store:

  • Skip (without errors) any entries that correspond to a module totally missing from the file system.
  • Skip (without errors) any entries that correspond to present-but-not-installed modules.
  • Add test coverage of these.

Remaining tasks

  1. Decide if we need better (actionable) warning messages. See #23. Yes.
  2. Decide if we need a warning message / log entry about orphaned system.schema entries for not-installed modules. See #30. Why not? See #31.
  3. We need to edit the CR for this.
  4. @xjm, @catch and I agreed that the warning messages should link to the CR for more info. "<a href=":link">More information about this error.</a> tacked on the end." See #45.
  5. <a href="#comment-13620341">#36.2: I'll add more comments. But yes that hunk matters, and no it doesn't need moduleExists() there. See #45.
  6. #36.3: Indeed, typo. s/non-existant/nonexistent/ (a vs. e, plus we don't need the hyphen). See #45.
  7. #40. See #45.
  8. Further reviews / improvements.
  9. RTBC.
  10. Commit.

User interface changes

New warnings printed on update.php if there are orphaned entries in system.schema k/v store. Two possible cases:

  • Module totally missing from the file system.
  • Modules that are present but not currently installed.

Module %name has an entry in the system.schema key/value storage, but is missing from your site.

Module %name has an entry in the system.schema key/value storage, but is not installed.

Screenshot showing a site with both kinds of orphaned entries:

 totally missing from filesystem and present-but-uninstalled.

If a site only has 1 or the other, a single message is displayed:

Screenshot of update.php with a single orphaned entry in system.schema key_value store for a module that is present but not installed.

API changes

None.

Data model changes

None.

Release notes snippet

TBD.

CommentFileSizeAuthor
#48 3136668-48.only-uninstalled.png139.91 KBdww
#48 3136668-48.both-warnings.png182.63 KBdww
#48 3136668.46_48.interdiff.txt5.38 KBdww
#48 3136668.45_48.interdiff.txt5.36 KBdww
#48 3136668-48.8_8_x.patch8.54 KBdww
#48 3136668-48.8_9_x.patch8.56 KBdww
#48 3136668-48.9_y_x.patch8.53 KBdww
#47 3136668-47.only-uninstalled.png133.23 KBdww
#47 3136668-47.both-errors.png169.64 KBdww
#46 3136668.33_46.interdiff.txt5.96 KBdww
#46 3136668-46.8_9_x.patch8.34 KBdww
#46 3136668-46.9_y_x.patch8.31 KBdww
#45 3136668.33_45.interdiff.txt5.93 KBdww
#45 3136668-45.8_8_x.patch8.31 KBdww
#34 3136668.31_33.interdiff.txt4.09 KBdww
#33 3136668.32_33.8_9_x.interdiff.txt3.46 KBdww
#33 3136668.32_33.8_8_x.interdiff.txt4.55 KBdww
#33 3136668-33.8_8_x.patch7.54 KBdww
#33 3136668-33.8_9_x.patch7.57 KBdww
#33 3136668-33.9_y_x.patch7.54 KBdww
#32 3136668.31_32.interdiff.txt4.28 KBdww
#32 3136668-32.8_8_x.patch7.81 KBdww
#32 3136668-32.8_9_x.patch6.09 KBdww
#32 3136668-32.9_y_x.patch6.06 KBdww
#31 3136668-31.only-uninstalled.png134.45 KBdww
#31 3136668-31.both-warnings.png168.11 KBdww
#31 3136668.29_31.interdiff.txt3.02 KBdww
#31 3136668-31.8_8_x.patch5.5 KBdww
#31 3136668-31.8_9_x.patch5.52 KBdww
#31 3136668-31.9_y_x.patch5.49 KBdww
#30 3136668.23_28.interdiff.txt3.4 KBdww
#29 3136668.27_28.interdiff.txt2.25 KBdww
#29 3136668-28.8_8_x.patch4.85 KBdww
#29 3136668-28.8_9_x.patch4.87 KBdww
#29 3136668-28.9_y_x.patch4.84 KBdww
#27 3136668.23_27.interdiff.txt3.97 KBdww
#27 3136668-27.orphaned-and-present.test-only.8_8_x.patch6.05 KBdww
#23 3136668.16_23.interdiff.txt2.26 KBdww
#23 3136668.15_23.interdiff.txt2.24 KBdww
#23 3136668-23.8_8_x.patch3.93 KBdww
#23 3136668-23.8_9_x.patch3.95 KBdww
#23 3136668-23.9_y_x.patch3.92 KBdww
#23 3136668-23.update_with_warning_message.png157.3 KBdww
#20 Screen Shot 2020-05-16 at 11.52.03.png33.91 KBshaktik
#16 3136668-16.8_9_x.patch3.21 KBdww
#16 3136668-16.9_y_x.patch3.17 KBdww
#15 3136668.14_15.interdiff.txt981 bytesdww
#15 3136668-15.8_8_x.patch3.18 KBdww
#14 3136668-14.8_8_x.do-not-test.patch2.29 KBdww
#9 3136668-9.patch1.23 KBpavnish
#6 3136668-test.patch1.23 KBdawehner
#5 3136668-5.patch1.24 KBdawehner

Comments

dawehner created an issue. See original summary.

dawehner’s picture

Issue summary: View changes
dawehner’s picture

Issue summary: View changes
dawehner’s picture

Issue summary: View changes
dawehner’s picture

StatusFileSize
new1.24 KB

Something like this resolves the problem for me. Turns out if you throw an exception catching that exception could be a good idea.
Working on a helpful testcase

dawehner’s picture

Status: Active » Needs review
StatusFileSize
new1.23 KB

This time with a test as well, sadly the patch above doesn't resolve that problem yet.

Status: Needs review » Needs work

The last submitted patch, 6: 3136668-test.patch, failed testing. View results

pavnish’s picture

Assigned: Unassigned » pavnish
pavnish’s picture

StatusFileSize
new1.23 KB

@dawehner in this patch i have remove extra space in comment.

pavnish’s picture

Assigned: pavnish » Unassigned
jyotimishra-developer’s picture

jyotimishra-developer’s picture

patch in #10 is failed to apply.

xjm’s picture

Priority: Normal » Critical
Issue tags: +D8 upgrade path, +beta target

Oops, missed this one...

dww’s picture

Version: 9.0.x-dev » 8.8.x-dev
StatusFileSize
new2.29 KB

Here's #5 + #6 in a single patch for 8.8.x.

Still fails locally. Here's why:

  1. When you get to the 'selection' page on update.php, it calls: update_retrieve_dependencies()
  2. That function does a similar loop:
        foreach (\Drupal::keyValue('system.schema')->getAll() as $module => $schema) {
    
  3. For each thing in 'system.schema', it calls module_load_install()
  4. module_load_install() jumps through a few more hoops before it calls drupal_get_filename().
  5. drupal_get_filename() does not throw exceptions on errors, but directly calls trigger_error(). :( There's no way to catch that. So the fix in #5 doesn't actually matter. Edit: I was wrong, see below.

I'm not sure how to fix this cleanly without lots of BC breaking.

The yucky / bloaty approach is to not call module_load_include() directly in update_retrieve_dependencies(), but to first use \Drupal::service("extension.list.module") and check that the module exists and is enabled before we try to call module_load_include(). Or something. :(

dww’s picture

Status: Needs work » Needs review
StatusFileSize
new3.18 KB
new981 bytes

Sweet, that wasn't nearly as bad as I feared. ;) This now passes locally. It's not even too terrible. Hope the inline comment is sufficient to explain why we need this.

Note: we still also need the fix from #5, so I'm leaving that in. If I take it out, the test starts failing again.

dww’s picture

StatusFileSize
new3.17 KB
new3.21 KB

Forward port to 8.9.x and 9.y.x branches.

dww’s picture

Oh, forgot to mention at #14. I slightly simplified the test:

-    $this->drupalLogin(
-      $this->drupalCreateUser(
-        [
-          'administer software updates',
-        ]
-      )
-    );
+    $this->drupalLogin($this->updateUser);

This test class already has a protected $updateUser with that permission, so we should re-use that instead of creating another.

The last submitted patch, 16: 3136668-16.9_y_x.patch, failed testing. View results

dww’s picture

Re: #18: Random fail:

There was 1 failure:

1) Drupal\Tests\media_library\FunctionalJavascript\WidgetUploadTest::testWidgetUploadAdvancedUi
"image-1.png" not found
Failed asserting that a boolean is not empty.

Re-queued...

shaktik’s picture

StatusFileSize
new33.91 KB

Hi @Dww,

this error is only getting on Drupal CI when automatic running or I check manually then working fine on drupal.org CI also in my local working fine.

I am getting the same error on
https://www.drupal.org/pift-ci-job/1683828
checked manually then working fine.

patch looks good to me

daffie’s picture

Status: Needs review » Needs work

The patch looks good.

The added test tests the problem as stated in the IS. I would like see a comment about the following line about why this line is here and what is does.

+++ b/core/modules/system/tests/src/Functional/UpdateSystem/UpdateScriptTest.php
@@ -401,6 +401,22 @@ public function testMissingExtension($extension_type) {
+    \Drupal::keyValue('system.schema')->set('my_already_removed_module', 8000);

The fix to update_get_update_list() is necessary, because without it the tests fails with:

Drupal\Tests\system\Functional\UpdateSystem\UpdateScriptTest::testNotExistingModuleInSchema
Exception: Drupal\Core\Extension\Exception\UnknownExtensionException: The module my_already_removed_module does not exist.
Drupal\Core\Extension\ExtensionList->get()() (Line: 265)

The fix to update_retrieve_dependencies() is necessary, because without it the tests fails with:

Drupal\Tests\system\Functional\UpdateSystem\UpdateScriptTest::testNotExistingModuleInSchema
Exception: User warning: The following module is missing from the file system: my_already_removed_module
drupal_get_filename()() (Line: 181)

I like the added log the error stuff. In this way we will get a better understanding about where these bugs come from. :)
With the added comment, the patch will be for me RTBC.

catch’s picture

I've added a brief note about this to #3130037: system.schema information gets out of sync with module list (which was already open to track modules having missing system.schema information), and retitled it so that it covers either direction of going out of sync.

Opened #3137197: Delete orphaned system.schema entries. to discuss automatically cleaning up the system.schema cruft (for Drupal 10).

Do we want to add a \Drupal::messenger() warning in this issue, so that we have an additional chance to alert site owners that something is up? It could result in more reports of this which may help to track down the root cause.

Another possible issue (or two):

1. If the module is in the code base, has the orphaned system.schema entry, but is not installed, will we then be locating and trying to run updates for it? i.e. have we accidentally re-introduced running updates on uninstalled modules when this happens?

2. If the module is not in the code base, but then is re-added, what happens if you try to install it again? Do we just ignore the system.schema entry and overwrite it, or does it cause problems?

I don't think #2 is as critical as this issue - since it would only prevent you re-installing that specific module as opposed to being able to run updates (i.e. we should split it out to a follow-up if it is), but #1 would be and could probably be handled here.

dww’s picture

Status: Needs work » Needs review
StatusFileSize
new157.3 KB
new3.92 KB
new3.95 KB
new3.93 KB
new2.24 KB
new2.26 KB

@shaktik Re: #20: I'm not understanding your comment. The tests are all working as expected, both on the drupal.org testbot and when running them locally. If you're seeing skipped tests locally, something is wrong with your testing environment. Helping you debug your setup is out of scope for me and my time today, sorry.

@daffie: Re: #21: Thanks for the review. Re: \Drupal::keyValue('system.schema')->set('my_already_removed_module', 8000);, I was hoping that the name of the test (testNotExistingModuleInSchema()) and the existing summary ("Tests that orphan schemas don't prevent updates.") was sufficient. But I'm always up for more comments, so here you go. ;)

@catch: Re: #22: Thanks for the review, follow-up and the questions.
Re: dsm(): Sure, I guess that's fine. For now, duplicated exactly the message that gets logged. However, I'm worried that the message is sort of scary sounding but totally non-actionable for 99% of site admins. :(

Screenshot of update.php when the site has an orphaned entry in the system.schema key/value store for a module that does not exist in the filesystem.

Module %name has a schema in the key_value store, but is not installed.

<hat class="average-site-builder">

  • So what?
  • Now what?
  • How do I fix this warning?
  • Drupal Is Broken(tm)!

</hat>

Not even drush gives you an easy way to clean up the k/v store. AFAIK, you have to do direct DB manipulations or PHP eval to try to clean this out.

Do we really want to present this to site admins like this? If so, I think we need a better message that either explains what to do, or at least links to a handbook page on d.o that does.

Re: #22.1: I can't fathom how adding code to update.inc that gives it more reasons to skip trying to run updates for something would re-introduce the bug you're talking about. 😉 Also, don't we already have existing test coverage of that original bug? If not, what happened?!? 😜 If so, why can't we trust it to make sure this hasn't re-broken it? I briefly skimmed through the rest of UpdateScriptTest.php and didn't see anything, but I'm not totally fluent in all the update.php tests and what they cover. Seems out of scope here to add such coverage if it doesn't already exist, especially since it seems impossible that this change would re-trigger that bug. This patch only makes it more likely that we don't try to run updates we shouldn't run.

Re: #22.2: That seems to work just fine:

# Clean slate, nothing installed, nothing in system.schema.
# Insert the bogus value:
% drush ev "\Drupal::keyValue('system.schema')->set('custom', 7000);"
# Verify it.
% drush ev "echo \Drupal::keyValue('system.schema')->get('custom')"
7000
% drush en custom
 [success] Successfully enabled: custom
% drush ev "echo \Drupal::keyValue('system.schema')->get('custom')"
8000

So probably NW for a better message to show admins and stuff in the logs. Perhaps we need a handbook page first so we can link to it. TBD. /shrug

dww’s picture

p.s. at #3110198-53: [META] Beta targets following Drupal 9.0.0-beta1 and 8.9.0-beta1 @catch wrote:

That will affect sites updating to 8.7.13 too, although only if they already have corrupted system.schema information in that specific way.

Not worth bot cycles for this (yet), but FYI, the 8_8_x patch applies cleanly to 8.7.x branch and the new test passes there, too.

daffie’s picture

Status: Needs review » Reviewed & tested by the community

Added a \Drupal::messenger() warning to the patch as requested by @catch.
Added a comment to the test as requested by myself.
The warning message text could/should be improved, only nobody has any idea.
As this issue is blocking the release of 9.0-rc1, I am not going to block it on a better warning message text.
All code changes look good to me.
For me it is RTBC.

catch’s picture

I can't fathom how adding code to update.inc that gives it more reasons to skip trying to run updates for something would re-introduce the bug you're talking about.

I don't mean that this issue will re-introduce a bug, I'm asking whether we have a separate bug related to orphaned system.schema entries that is not covered here, potentially introduced by #2917600: update_fix_compatibility() puts sites into unrecoverable state.

The current patch and test coverage covers:

A module, that was previously installed, that has orphaned data in system.schema, that is no longer in the file system.

It does not cover:

A module, that was previously installed, that has orphaned data in system.schema, that is still in the file system.

In that case, there will probably not be an exception thrown from ::checkIncompatibility(), and system.schema is returning 8000 or whatever instead of SCHEMA_UNINSTALLED - so, what happens? Do we hit an error later? Do the updates get added to the list? Does it get filtered out again somewhere when we switch back to extension.list instead of system.schema in a foreach so that things are eventually fine? Even if there's not a functional bug in the end, we should add test coverage for that.

dww’s picture

@catch: Thanks for clarifying! Now I understand you. Indeed, that's broken. :( Sounds like we need to fix that here?

Status: Reviewed & tested by the community » Needs work
dww’s picture

Status: Needs work » Needs review
StatusFileSize
new4.84 KB
new4.87 KB
new4.85 KB
new2.25 KB

This fixes the new test. Not sure if this is cool, or will break something else. Let's see if the bot spots any other troubles.

dww’s picture

Issue summary: View changes
StatusFileSize
new3.4 KB

Okay, so that's encouraging. The bot is happy with all the other update tests with the fix in #29. Yay.

Here's the interdiff between patches 23 and 28, which might be more clear than the intervening interdiffs since there's nothing about drupalci.yml in this.

Updating summary a bit now that this is getting closer to done.

One thought on the fix from #29: do we want to detect that case explicitly and add another dsm/log message about it? Honestly, the existing message is more accurate for the present-but-not-installed case:

Module %name has a schema in the key_value store, but is not installed.

Perhaps we should change the message in the not-present case to something like:

Module %name has a schema in the key_value store, but is missing from your site.

If we're changing the messages, perhaps we can make them more clear / actionable, too (see #23).

Thoughts?

Thanks,
-Derek

dww’s picture

Issue summary: View changes
StatusFileSize
new5.49 KB
new5.52 KB
new5.5 KB
new3.02 KB
new168.11 KB
new134.45 KB

This handles the possible error conditions separately so we can have more specific warning messages:

 totally missing from filesystem and present-but-uninstalled

dww’s picture

StatusFileSize
new6.06 KB
new6.09 KB
new7.81 KB
new4.28 KB

More specific tests. Not sure this is an improvement over #31, but instead of checking the whole page, make sure the status text is in a status message, and that the warning text is in a warning message. /shrug Stark doesn't use classes, so instead of searching for div.messages-status, we need to xpath() for @aria-label="Status message"...

Adds coverage that there aren't unexpected warnings.

Also adds coverage for the situation where both warnings are displayed.

Finally, I'm removing a stay visit to the status report that's from the original test in #6:

+++ b/core/modules/system/tests/src/Functional/UpdateSystem/UpdateScriptTest.php
@@ -400,6 +400,28 @@ public function testMissingExtension($extension_type) {
+    $this->drupalGet($this->statusReportUrl);

Seems we don't need that as part of this test...

dww’s picture

StatusFileSize
new7.54 KB
new7.57 KB
new7.54 KB
new4.55 KB
new3.46 KB

Sorry, patches in #32 were a bit wonky. Didn't correctly apply the changes to all the branches. Try these, instead.

dww’s picture

Issue summary: View changes
StatusFileSize
new4.09 KB

In case it's helpful, interdiff between #31 and #33...

daffie’s picture

Status: Needs review » Reviewed & tested by the community

A module, that was previously installed, that has orphaned data in system.schema, that is still in the file system.

This is what @catch wants to add to the patch. The added check: if (!$module_handler->moduleExists($module)) { does exactly that. There is also automatic testing added in the patch for that.
All points of @catch are addressed.
All code changes look good.
Back to RTBC.

catch’s picture

Status: Reviewed & tested by the community » Needs review

This is looking a lot better, comments are not major but the second one means back to Needs Review.

  1. +++ b/core/includes/update.inc
    @@ -340,11 +341,32 @@ function update_get_update_list() {
    +      }
    +    }
    +    // It is possible that the system schema has orphaned entries, so the
    +    // incompatibility checking might throw an exception.
    +    catch (UnknownExtensionException $e) {
    +      $args = ['%name' => $module];
    +      \Drupal::messenger()->addWarning(t('Module %name has a schema in the key_value store, but is missing from your site.', $args));
    +      \Drupal::logger('system')->notice('Module %name has a schema in the key_value store, but is missing from your site.', $args);
           continue;
         }
    +    // There might be orphaned entries for modules that are in the filesystem
    +    // but not installed. Also skip those, but warn site admins about it.
    +    if (!$module_handler->moduleExists($module)) {
    +      $args = ['%name' => $module];
    +      \Drupal::messenger()->addWarning(t('Module %name has a schema in the key_value store, but is not installed.', $args));
    +      \Drupal::logger('system')->notice('Module %name has a schema in the key_value store, but is not installed.', $args);
    +      continue;
    +    }
    +
    

    +1 on the changed messages. Also makes it much clearer exactly what the different error conditions are by moving (compared to earlier patches) the ::moduleExists() check under a dedicated comment.

  2. +++ b/core/includes/update.inc
    @@ -631,10 +653,15 @@ function update_already_performed($module, $number) {
       // the same order that \Drupal::moduleHandler()->invokeAll() does.
       foreach (\Drupal::keyValue('system.schema')->getAll() as $module => $schema) {
    -    if ($schema == SCHEMA_UNINSTALLED) {
    +    // Skip modules that are entirely missing from the filesystem here, since
    +    // module_load_install() will call trigger_error() if invoked on a module
    +    // that doesn't exist. There's no way to catch() that, so avoid it entirely.
    +    if ($schema == SCHEMA_UNINSTALLED || !$extension_list->exists($module)) {
           // Nothing to upgrade.
           continue;
         }
    

    This doesn't have the ::moduleExists() check, does that matter? Also the comment doesn't mention orphaned system.schema entries. Is the hunk even needed with the rest of the patch?

  3. +++ b/core/modules/system/tests/src/Functional/UpdateSystem/UpdateScriptTest.php
    @@ -401,6 +401,68 @@ public function testMissingExtension($extension_type) {
    +
    +    // First, insert a bogus value into the system.schema key/value storage for
    +    // a non-existant module. This replicates what would happen if you had a
    +    // module installed and then completely remove it from the filesystem
    

    Nit: shouldn't this be existent? Or is that British vs. American?

    I think there's an extra step involved to reach this condition 1. You had the module installed but removed it from the filesystem without uninstalling 2. You 'manually' uninstalled in extension.list without removing the system.schema entry. If the module is in extension.list but not the filesystem, that's a different problem for which we already have error messages.

    Also maybe this is actually how people are getting into this position? If so we might not actually have a core bug causing this as such.

alexpott’s picture

+++ b/core/includes/update.inc
@@ -340,11 +341,32 @@ function update_get_update_list() {
+  /** @var \Drupal\Core\Extension\ModuleHandler $module_handler */
+  $module_handler = \Drupal::moduleHandler();
...
+    // There might be orphaned entries for modules that are in the filesystem
+    // but not installed. Also skip those, but warn site admins about it.
+    if (!$module_handler->moduleExists($module)) {

I don;t think we need a new dependency here. The extension list know which modules are installed. See \Drupal\Core\Extension\ExtensionList::getInstalledExtensionNames()

pavnish’s picture

Assigned: Unassigned » pavnish
Status: Needs review » Needs work
pavnish’s picture

Status: Needs work » Needs review

Hi @alexpott this the protected method i think we can not use directly in .inc file.This function can we use by using the class.
One more think this function has implemented on "extension.list.module" service in protected manner which internally use "$this->moduleHandler->getModuleList()" .
So i think it was not an issue
Please correct me if am wrong.

alexpott’s picture

@pavnish good point. We can get a list using \Drupal\Core\Extension\ExtensionList::getAllInstalledInfo() and then check if the module is not in this list.

alexpott’s picture

One concern is what is the correct action to take at this point. We can:

  • Report the error and soldier on like we're doing here
  • Halt the update - your code and database state is inconsistent. This has problems because you might need a security update and this would prevent you until you've manually fixed the table.
  • Report the error and clean up the state. This has problems too because maybe there's other stuff left lying around from the module.

All pretty awkward but what we're currently doing is probably best.

catch’s picture

We have #3137197: Delete orphaned system.schema entries. for deleting entries, I'm suggesting doing that in Drupal 10 in an update.

The big question with this is whether things getting out of sync is due to force-uninstalls by admins - in which case it's good to handle and warn about it, but ultimately self-inflicted, or due to core and contrib bugs - like a fatal error during uninstall. And also whether we can ever prevent either of those from happening permanently.

shaktik’s picture

dww’s picture

Assigned: pavnish » dww
Issue summary: View changes
Status: Needs review » Needs work
Issue tags: +Needs change record

Discussed this in the #d9readiness meeting today. I'll work on the following:

  1. We need a CR for this.
  2. @xjm, @catch and I agreed that the warning messages should link to the CR for more info. "<a href=":link">More information about this error.</a> tacked on the end."
  3. #36.2: I'll add more comments. But yes that hunk matters, and no it doesn't need moduleExists() there. If you remove that hunk, the test fails like so:
    There was 1 error:
    
    1) Drupal\Tests\system\Functional\Update\UpdateScriptTest::testOrphanedSchemaEntries
    Exception: User warning: The following module is missing from the file system: my_already_removed_module
    drupal_get_filename()() (Line: 295)
    

    As it says, we can't call module_load_install() on something not in the filesystem or we get an uncatchable trigger_error(), not an exception. This is actually in update_retrieve_dependencies(). We don't need to filter out not-installed here, because that happens in update_get_update_list(). We could also filter those out here, and the tests still pass, but that seems like maybe scope creep? I defer to core committers on their preference for this.

  4. #36.3: Indeed, typo. s/non-existant/nonexistent/ (a vs. e, plus we don't need the hyphen).
  5. #40.
dww’s picture

Assigned: dww » Unassigned
Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs change record +Needs change record updates
StatusFileSize
new8.31 KB
new5.93 KB

Very preliminary CR here: https://www.drupal.org/node/3137656 -- If anyone wants to edit that to be real, please do. ;)

This fixes everything else I mentioned in #44. This is only the 8.8.x branch patch. I'll forward port after breakfast, assuming folks are happy with all this.

dww’s picture

StatusFileSize
new8.31 KB
new8.34 KB
new5.96 KB

Forward ports.

dww’s picture

Issue summary: View changes
Issue tags: -Needs change record updates
StatusFileSize
new169.64 KB
new133.23 KB

Initial real version of the CR: https://www.drupal.org/node/3137656/revisions/view/11880555/11880653
Also, refreshing the screenshots, now that we have a link in the warning messages.

dww’s picture

Issue summary: View changes
StatusFileSize
new8.53 KB
new8.56 KB
new8.54 KB
new5.36 KB
new5.38 KB
new182.63 KB
new139.91 KB

I reworded the warnings to be a bit more useful for mere mortals:

Module %name has a schema in the key_value store, but is missing from your site.
Module %name has a schema in the key_value store, but is not installed.

  • If people are going to be fixing this, they need to know the actual k/v table name ("system.schema").
  • What's a "key_value store"? Is that where I buy valuable keys? Huh?

Now:

Module %name has an entry in the system.schema key/value storage, but is missing from your site.

Module %name has an entry in the system.schema key/value storage, but is not installed.

p.s. "Maybe "key/value service..." would be better than "storage"?

daffie’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community

The CR is to me good enough. It has a good describtion about the newly added warning message. Including what a siteowner can do to cleanup the error.
All shown warnings are also logged and all have a link to the CR.
There are 2 different warnings that are shown, depending on whether the source module is on the file system or not. For both and for the combination is automatic testing added.
All code changes look good to me and all are very commented.
We have a followup for cleaning up the orphaned system.schema entries. See: #3137197: Delete orphaned system.schema entries..
For it is all good enough. We need to ship Drupal 9.0 and not spending a lot of time trying to get this issue perfect. Even so, I must say that the effort of @dww is very much appreciated!
For me it is RTBC.

  • catch committed 5d95f2e on 9.1.x
    Issue #3136668 by dww, dawehner, pavnish, catch, daffie, alexpott, xjm:...

  • catch committed c514ebf on 9.0.x
    Issue #3136668 by dww, dawehner, pavnish, catch, daffie, alexpott, xjm:...
catch’s picture

Status: Reviewed & tested by the community » Fixed

Thanks for the CR and the additional comments/message improvements, all looks good to me now.

Committed/pushed to 9.1.x, cherry-picked to 9.0.x, and then the 8.9.x and 8.8.x patches, thanks!

  • catch committed dd18da9 on 8.9.x
    Issue #3136668 by dww, dawehner, pavnish, catch, daffie, alexpott, xjm:...
dww’s picture

Assigned: Unassigned » catch
Status: Fixed » Patch (to be ported)

@catch Thanks! Looks like you didn't push the 8.8.x commit...

  • catch committed e4db674 on 8.8.x
    Issue #3136668 by dww, dawehner, pavnish, catch, daffie, alexpott, xjm:...
catch’s picture

Status: Patch (to be ported) » Fixed

Hmm, now pushed!

dww’s picture

Assigned: catch » Unassigned

Wonderful, thanks.

Status: Fixed » Closed (fixed)

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