Problem/Motivation
If config makes its way to that active/target store with a missing UUID Drupal's config system has trouble handling the value. This can lead to database stores in an inconsistent and difficult to fix state requiring direct modification of the database store in the database.
Steps to reproduce
Users have ended up in this state but difficult to isolate the cause. Only reliable way seems to be manual database interactions.
Proposed resolution
Make StorageComparer more resilient to the edge case and self heal the target by triggering a recreation of the config item.
Remaining tasks
User interface changes
n/a
Introduced terminology
n/a
API changes
n/a
Data model changes
n/a
Release notes snippet
n/a. Normal bug fix.
Original report by john cook
Config import creates "Undefined index: uuid" notice
In our use case we have two seach_api index sett-ups; one for local development and one for staging / produdction.
On deployment we use drush cset search_api.server.index status false to select the appropiate configuration.
This works fine for trash and rebuild on the local development machines, but when the configuration in imported on the persitent environments the following error is produced:
Notice: Undefined index: uuid in Drupal\Core\Config\StorageComparer->addChangelistUpdate() (line 262 of docroot/core/lib/Drupal/Core/Config/StorageComparer.php)
#0 docroot/core/includes/bootstrap.inc(548): _drupal_error_handler_real(8, 'Undefined index...', '/mnt/www/html/h...', 262, Array)
#1 docroot/core/lib/Drupal/Core/Config/StorageComparer.php(262): _drupal_error_handler(8, 'Undefined index...', '/mnt/www/html/h...', 262, Array)
#2 docroot/core/lib/Drupal/Core/Config/StorageComparer.php(206): Drupal\Core\Config\StorageComparer->addChangelistUpdate('')
#3 docroot/core/modules/config/src/Form/ConfigSync.php(181): Drupal\Core\Config\StorageComparer->createChangelist()
#4 [internal function]: Drupal\config\Form\ConfigSync->buildForm(Array, Object(Drupal\Core\Form\FormState))
#5 docroot/core/lib/Drupal/Core/Form/FormBuilder.php(514): call_user_func_array(Array, Array)
#6 docroot/core/lib/Drupal/Core/Form/FormBuilder.php(271): Drupal\Core\Form\FormBuilder->retrieveForm('config_admin_im...', Object(Drupal\Core\Form\FormState))
#7 docroot/core/lib/Drupal/Core/Controller/FormController.php(74): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\config\Form\ConfigSync), Object(Drupal\Core\Form\FormState))
#8 [internal function]: Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#9 docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#10 docroot/core/lib/Drupal/Core/Render/Renderer.php(574): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#11 docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#12 docroot/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#13 [internal function]: Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#14 /mnt/www/html/hiscoxukstg/vendor/symfony/http-kernel/HttpKernel.php(144): call_user_func_array(Object(Closure), Array)
#15 /mnt/www/html/hiscoxukstg/vendor/symfony/http-kernel/HttpKernel.php(64): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1) #16 docroot/core/lib/Drupal/Core/StackMiddleware/Session.php(57): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#17 docroot/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(47): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#18 docroot/core/modules/page_cache/src/StackMiddleware/PageCache.php(99): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#19 docroot/core/modules/page_cache/src/StackMiddleware/PageCache.php(78): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#20 docroot/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(47): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#21 docroot/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(50): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#22 /mnt/www/html/hiscoxukstg/vendor/stack/builder/src/Stack/StackedHttpKernel.php(23): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#23 docroot/core/lib/Drupal/Core/DrupalKernel.php(652): Stack\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#24 docroot/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#25 {main}.
| Comment | File | Size | Author |
|---|---|---|---|
| #33 | 2863785-d11.patch | 3.08 KB | graber |
| #24 | 2863785-24.patch | 3.08 KB | neclimdul |
Issue fork drupal-2863785
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
john cook commentedI've create a patch that adds a check to ensure that
$target_data['uuid']has been set. This makes sure that the configuration is recreated before trying to compare uuids.Comment #3
john cook commentedThis adds checks for ConfigEntityStorageInterface::getIDFromConfigName() returning NULL.
Comment #7
firfin commentedApplied the patch on a Drupal 8.5.5 running on php 7.0 applied with just some offsets, no problems. Afterwards no more UUID errors.
Code looks clean also.
That said I have absolutely no clue as to this is the right solution to solve the error.
Comment #8
alexpottAt the very least this needs tests.
Also the patch in #3 is failing tests.
I think a more complete description of the problem and perhaps a test that causes the problem would be a good place to start since I have no idea why the config importer is dealing with configuration entities without a UUID.
Comment #10
claudiu.cristea@alexpott
We hit the same error on a project built in the early stages of D8. Some config entries from the database were imported without an UUID, directly from the module's default config. Don't ask how they landed there without an UUID. Perhaps because the project used initially a very old version of
config_syncmodule. I have no clear understanding. The fact is that the site is in production for > 2 years and the configs are there from a long time.I think the solution from #2 makes sense, as it will replace the config from the database as if their UUID is different and would heal the database store.
Comment #13
achapTo add some more context to this issue.
I experienced it on a project that was heavily using config_split that I inherited that was creating new splits from the config in an example split directory via a script. These example configs didn't have a uuid so we got the error message. I was able to run the import, which completed successfully and after page refresh the error message went away. Obviously, that's not a "fix" but there you go.
I have no idea why the original config didn't have a uuid.
Comment #19
jungleFYI, admin_toolbar module's
admin_toolbar.settings.ymlexported has no uuid key.Drupal core: 9.3.22
admin_toolbar:3.2.1
Comment #20
junglecaptcha.settings.yml exported from captcha as well
Comment #22
prashant.cWe are also experiencing this issue on our site which was built on Drupal 8.6 and now upgraded to Drupal 10.0.8. Some of the configs like admin toolbar, advagg, etc.do not have UUIDs, I also doubt it is happening due to those.
Changing to Major as it is a blocker during config export/import.
Comment #24
neclimdulWebform also triggers this with its default contact form when installing from config.
Don't think a notice qualifies for major. If someone could help me recreate the fatal from the load failures addressed in #4 maybe we can bump it back but I suspect that might be a different maybe related issue. Until then it will also be difficult to create a realistic test for it.
Here's an updated patch for Drupal 10 with just the uuid handling (since I don't know how to recreate and test the load failure) and a test.
Comment #25
neclimdulThis asserts the existing behavior with the undefined property evaluating to null. Is recreating actually correct though? That seems kinda odd.
I don't know if the order matters here. Or if we need to assert it since its probably better tested else where. I would appreciate someone more familiar with the methods chiming in here.
Comment #26
needs-review-queue-bot commentedThe Needs Review Queue Bot tested this issue.
While you are making the above changes, we recommend that you convert this patch to a merge request. Merge requests are preferred over patches. Be sure to hide the old patch files as well. (Converting an issue to a merge request without other contributions to the issue will not receive credit.)
Comment #29
alexpott@neclimdul if webform is creating entities without a UUID then that's a bug in webform - no?
Comment #30
therobyouknow commentedI got this doing a drush cex
A drush cr
- clear cache
appeared to resolve it
My Drupal version 10.0.9 (need to upgrade to latest)
Comment #31
therobyouknow commentedthis has come back
when developing drupal code to share with others, I would want to remove the uuid
https://drupal.stackexchange.com/questions/295320/best-practice-remove-u...
however, I believe in doing so, it causes the "Undefined index: uuid". This post appears to explain: https://drupal.stackexchange.com/questions/204859/site-uuid-in-source-st...
Comment #33
graber commentedRe-rolled for a certain project but yes, it's the config that should be fixed.
Comment #35
neclimdulyeah, I think the problem was more that the config to fix was the database store so fixing would require manual queries to serialized data structures. That or recreating the config by deleting and re-importing manually similar to proposed solution. The intention of the patch as claudiu put it was to let the config system detect and heal a bad database store.
Looking at the patch after many years, that's a bit difficult to see so I split the code out with a comment so hopefully that will make review and acceptance easier.
At this point I think config is at lot more stable and users that would have run into this probably already have and worked through but the patch should guard against future users getting into a bind.
Also updated title and IS to reflect what's being proposed.
Comment #36
andypostComment #37
smustgrave commentedRemoving the test tag as it doesn't cause an error but does generate a warning
Can't run in the pipeline because of my role so did it locally.
Very neat approach setting it to NULL to fix itself. Comment is very nice too.
0 objections LGTM.
Comment #38
alexpottThis does seem like a reasonable hardening but I don't think we should actually be setting the uuid in the target data here. This ends up changing the target data when it should not. Leaving a review and suggestion on the MR.
Comment #39
neclimdulReview addressed
Comment #40
smustgrave commentedFeedback from @alexpott appears to be addressed
Comment #41
john.oltman commentedComment #42
john.oltman commentedUpdated the title since the MR does not actually repair storage anymore (at least in any different way than before).
If I am right, the issue description needs an update. If I am wrong, my apologies, please reset the title back. However, from what I can tell, the behavior of storage has not changed in the MR, other than an edge case no longer throwing a notice. I ran into this notice with config from the editoria11y contrib module, and the MR fixed it.
Comment #43
alexpott@john.oltman - well I guess you could consider it repairing when you run the import and it recreates the config with a uuid. But your new title is more accurate.
Comment #44
alexpottCommitted and pushed c8bda45c62b to main and 23a4af7850e to 11.x. Thanks!
Committed 89b938b and pushed to 11.4.x. Thanks!
Comment #49
vidit.anjaria commented