Problem/Motivation
Coming from #2677574: All Blocks removed from regions after checking "Show Global blocks".
If an admin submits a block layout form that is empty (has no blocks), all blocks in all themes are left in a broken state (they do not appear through the admin UI).
Steps to reproduce
- Install Drupal core with the "Standard" install profile.
- Enable the "Stark" theme, setting it as default.
- At Admin > Structure > Block layout (admin/structure/block), delete all blocks for the Stark theme. After deleting the blocks, click the "Save blocks" button.
- Navigate to Admin > Structure > Block layout > Bartik (admin/structure/block/list/bartik). Note that all blocks have disappeared. The following screenshot illustrates the resulting page.

Source of bug
In BlockListBuilder::submitForm() we pass a form state value directly to a ::loadMultiple() call and then iterate through the resulting entities, making changes to each:
$entities = $this->storage->loadMultiple(array_keys($form_state->getValue('blocks')));
/** @var \Drupal\block\BlockInterface[] $entities */
foreach ($entities as $entity_id => $entity) {
In the case that there are no blocks present on the form:
- An empty string is returned from
$form_state->getValue('blocks'), and so all items in the storage are loaded, iterated, modified (includingweightandregionproperties set toNULL), and saved. - Without a
regionvalue, blocks don't show up in the UI.
Mitigating factors
Because of the block cloning that occurs when a theme is initially installed (see block_theme_initialize(), it's uncommon to have a theme enabled with no blocks; and, if there are no blocks, there is no reason to submit the form.
However, the bug can easily be triggered by contrib modules modifying the block management form. Specifically, the Block Visibility Groups module provides an enhancement that includes filtering blocks to show only those in a given visibility group (initially, none). See #2677574: All Blocks removed from regions after checking "Show Global blocks".
Proposed resolution
Examine the value returned by $form_state->getValue('blocks') and pass to ::loadMultiple() only if not empty.
Remaining tasks
User interface changes
API changes
Data model changes
| Comment | File | Size | Author |
|---|---|---|---|
| #44 | 2779321.patch | 2.92 KB | catch |
| #44 | 2779321-interdiff.txt | 1.73 KB | catch |
| #41 | 2779321.patch | 1.42 KB | catch |
| error_before_patch_2779321-34.png | 99.37 KB | supriyak | |
| after_patch_2779321-34.png | 577.52 KB | supriyak |
Comments
Comment #2
nedjoComment #3
nedjoValue returned from
$form_state->getValue('blocks')if no blocks are present is an empty string (notNULL), so testing forempty()rather thanis_null().Comment #4
nedjoComment #15
ranjith_kumar_k_u commentedRe-rolled for 9.3
Comment #17
meenakshi_j commentedfixed the fails.
Comment #20
smustgrave commentedVerified the issue when deleting all blocks you can't save the form.
Though I did not see the blocks from other themes go away.
This will 100% need a test case but it should be super simple
Comment #21
smustgrave commentedAdding a test case
Comment #23
deepalij commentedComment #25
deepalij commentedComment #26
Manibharathi E R commentedPatch #21 Tested and Applied successfully on Drupal 9.5.x.
Steps:
1. Install Drupal
2. Enable the "Stark" theme, setting it as default.
3. At Admin > Structure > Block layout (admin/structure/block), delete all blocks for the Stark theme. After deleting the blocks, click the "Save blocks" button.
4. Getting the PHP type Error.
5. Apply the patch
6. Click the "save blocks button" its redirect blocks listing page.
Comment #27
kristen polNot sure why this was moved to 9.5 in #25. Note that the patch in #21 applies (with fuzz) to
10.0.xand10.1.x.Comment #28
kristen polNitpick: I would make this comment one line and not note the method (
loadMultiple) in it.Comment #29
pooja saraah commentedAddressed the comment #28
Attached patch against Drupal 10.1.x
Comment #30
bebalachandra commentedReproduced problem according to steps given in problem statement. Tested on 10.1 referring to #26 #27 #28 #29.
Getting error while saving changes to blocks in stark theme(attached screenshot)
After installing #29 patch error which was generating while saving changes resolved.
Also the breakdown of all other themes block also resolved and looks good with 10.1
Moving this issue to RTBC.
Attached screenshot for reference
Comment #31
alexpottI think we should fix this slightly differently. If we press save and there is nothing to do I think we should tell the user. With the current fix we're going to tell the user
'The block settings have been updated.'when we've done nothing. Is that correct? I think we could consider changing the ::validateForm() method to tell the user it's not going to do anything. Something like this:Comment #32
mukhtarm commentedAdding the patch by addressing the comment #31
Comment #33
akram khanAddress #31
Comment #34
akram khanUpdated patch and address #31 fixed code of #30.
Fixing CCF #33 Needs Review
Comment #35
akram khanComment #36
supriyak commentedPatch #34 Tested and Applied successfully on Drupal 10.1.x.
Comment #37
smustgrave commentedTested #34 and it worked.
See that feedback from #31 has been addressed also.
Comment #39
catchCommitted/pushed to 10.1.x, cherry-picked to 10.0.x and 9.5.x.
Note I didn't add commit credit for duplicated manual testing, once is plenty.
Comment #40
berdirAfter-the-commit review, coming here because this requires a reroll of #2910353: Prevent saving config entities when configuration overrides are applied
The committed patch is a little bit strange, because I don't think the submitForm() changes are necessary now that the validation is in place, because you can't end up there with an empty block list?
Additionally, loadMultiple() only returns all entities if you explicitly pass NULL. An empty array is a no-op and returns nothing. I suppose the form value really is null. FWIW, in PHP 8, array_keys(NULL) is actually a type error, so in Drupal 10, the worst that could happen there is a fatal error and not breaking all your config (yay stricter type handling).
I don't think it's worth reopening this to revert the submitForm() changes, but happy to do so if others/catch think that makes sense.
Comment #41
catchThat's a good point with the submitForm changes. Here's a patch that just reverts that hunk, if that passes I may commit as-is since it's just an unnecessary hunk that we otherwise could have removed from the original patch on commit.
Comment #42
alexpottWe also need a follow-up here to wrap the UI text in
$this->t().Plus we could add testing that this message appears.
Comment #43
berdirFailed but that test looks unrelated?
Setting to needs work for #42. The test comment should then also be updated to that you actually can not save?
Comment #44
catchThis is tipping into follow-up issue territory now, but here's those changes.
Comment #45
berdirLooks good to me.
Comment #46
alexpottLet's do a quick commit here and forget it ever happened :)
Committed and pushed b5b2951668 to 10.1.x and 60ce4e1407 to 10.0.x and 9b61f274e7 to 9.5.x. Thanks!