Needs work
Project:
Drupal core
Version:
main
Component:
theme system
Priority:
Major
Category:
Bug report
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
20 Jun 2016 at 21:04 UTC
Updated:
1 Dec 2025 at 00:39 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
sylus commentedComment #3
sylus commentedComment #4
sylus commentedMoving this to bootstrap as couldn't replicate on Drupal Core but as soon as switched to bootstrap theme, then this issue popped up.
Comment #5
markhalliwellFeel free to try and figure out what's going on there. IMO this really isn't that big of a deal.
Comment #6
sylus commentedThe `menu--main.html.twig` is always the most specific suggestion, so I can't leverage the `menu--main--customization.html.twig` theme suggestion ever, as the regular one is always superceding. This breaks the proper theming workflow and makes it impossible to do custom menu's.
Strangely this only occurs for menu suggestions and doesn't affect any others like blocks.
Will try to figure out what is causing this but thanks for taking the time to comment :)
Comment #7
markhalliwellNo, that's not how theme suggestions work. They work from the bottom up and stop at the first matching one. Your own code proves this (see where the X is):
Comment #8
sylus commentedApologies I actually wrote those theme suggestions based on memory so the 'X' was wrong here is a recent cut/paste. You can see that both are active and never takes my most specific menu template.
I've updated the OP with the actual code copied.
Comment #9
sylus commentedComment #10
sylus commentedAttaching an image showing the templates I have including `menu--main--wxt-bootstrap-main-menu--wet-boew.html.twig` which is the one I want to take hold.
Comment #11
sylus commentedComment #12
sylus commentedComment #13
sylus commentedI read your most recent comment stating it goes from the bottom up and stops on the first matching pattern. If that were the case wouldn't it only ever match menu.html.twig?
Comment #14
markhalliwellSorry, I meant top down.
So, I've actually been stepping through this. From what I can tell this is, in fact, a core "bug".
Looking through
\Drupal\Core\Theme\ThemeManager::render, I can see that the suggestions provided are actually correct. Where the "break down" actually occurs is intwig_render_template, specifically with the twig_debug suggestion output. Basically, it just merges suggestions without first seeing if they are already in the array. This can cause duplicates to appear if the suggestions were derived from splitting whatever was passed to#themeusing the__notation.So this is really just a display issue, it doesn't actually affect any of the logic in which theme hook suggestion is chosen.
I'll post a patch here shortly.
Comment #15
markhalliwellActually, this is a pretty major bug after all.
It turns out that
\Drupal\Core\Theme\ThemeManager::renderisn't doing what it's supposed to be doing after all. Even with the duplicates removed, themenu__toolbar__adminsuggestion should be appearing at the top. It is not.This is because the original theme hook that was passed to
#themeis never actually added to the$suggestionsarray. This means that if someone actually implementedmenu--toolbar--admin.html.twig, it's theme registry info wouldn't be used, only themenu__toolbarwould be.Comment #16
markhalliwellComment #18
sylus commentedJust chiming in here that the latest patch does indeed solve the problem and the appropriate template is now being called.
Thank you so much to @markcarver for the detailed inspection and analysis of the problem. ^_^
Here is the test currently failing though might be a false positive as the order being checked seems wrong:
Comment #20
davy-r commentedThe patch doesn't completely fix the issue.
Test 1
Result: FAIL, wrong order of displayed suggestions
Available templates: "input.html.twig"
Rendered template: "input.html.twig"
Debug output:
Test 2
Result: OK
Available templates: "input.html.twig", "input--search.html.twig"
Rendered template: "input--search.html.twig"
Debug output:
Test 3
Result: OK
Available templates: "input.html.twig", "input--search.html.twig", "input--search--search-block-form.html.twig"
Rendered template: "input--search--search-block-form.html.twig"
Debug output:
Comment #21
davy-r commentedTried a different approach in a attempted to resolve the issue. I don't have in-depth knowledge about the theme_hook_suggestions, but this seems to be resolving the issue in my case..
Comment #23
davy-r commentedThis morning I've been working though the process of determining the file name suggestions.
ThemeManager
#1: hook_theme_suggestions_HOOK is adding the "base" suggestions to $suggestions.
#2: When the theme implementation was invoked with a direct theme suggestion (like '#theme' => 'node__foo__bar') AND there is a template for that suggestion, then that suggestion is added to $suggestions.
#3: hook_theme_suggestions_HOOK_alter and hook_theme_suggestions_alter may modify the $suggestions, and add any suggestions before and/or after the current $suggestions.
#4: The $suggestions array is reversed and the first template suggestion that exists as a template, is being set as the template_file that is used for rendering.
Twig engine
- Attempts to redetermine the suggestions and print these as the file name suggestions.
In the attached patch I build a complete array of $suggestions, which always includes the suggestions from direct theme suggestion (like '#theme' => 'node__foo__bar'). Just before rendering I add the $suggestions to the $variables, to make sure we pass the file name suggestions that were actually used. In the Twig engine we can now just print the file name suggestions as they where actually used (instead of trying to redetermine them).
edit: ThemeSuggestionsAlterTest failing, will have a look on that later this week..
Comment #25
davy-r commentedComment #26
davy-r commentedIt turned out that the base suggestion should always have the lowest priority.
Comment #27
davy-r commentedComment #28
markhalliwellPatch from #26 seems to be working just fine. Setting back to CNW for tests of the OP.
Comment #29
acbramley commentedI'm not sure if this is related but I've found another issue to do with the base themes used in ThemeManager::alterForTheme where if you have the following theme structure:
- foo
-- bar
--- baz
And foo and bar both implement hook_theme_suggestions_alter, the suggestions from foo will appear after the suggestions from bar.
We have this issue with a subtheme of bootstrap that has some templates for form inputs, then site specific subthemes of that are adding their own templates but they are not being used. Other places in the registry reverse that base themes array before iterating over it so maybe that's also causing issues here?
Comment #30
lauriii@Cottser, @alexpott, @xjm, @joelpittet, and I discussed this and agreed that this is a major bug because this bug causes theme suggestions to work in a very unpredictable way. There is also no known workaround for this bug.
Comment #32
sylus commentedJust adding a related issue that is also addressing same area of code.
Comment #33
mian3010 commentedAttached new patch that applies to 8.3.x
Comment #34
davy-r commentedComment #35
sudhanshug commentedChanging status to queue the last submitted(from #33) patch for tests
Comment #36
sylus commentedComment #37
sylus commentedComment #40
gambryThanks everyone for the work done so far!
A comment explaining why we slice with offset 1 can help the reader. I'm assuming that's because element in position 0 is always the original hook ($hook = $original_hook = $derived_suggestion), and so already checked by previous condition
if (!$theme_registry->has($hook)){}? (and if so, do we need array_slice() at all? Suggestion: why don't we removed the firstif (!$theme_registry->has($hook)){}and the array_slice() at all?)We now slice omitting last element of the array. Again, maybe a comment describing why we do it would benefit the reader. Also splitting the 2 condition may help readability, as my understanding is they don't relate each other?
Also, why do we array_reverse() the slice of derived_suggestions? aren't suggestions already in the right specificity order (more -> less)?
Missing period.
This logic is probably wrong. It doesn't work for instance with Views (views_view) suggestions (after #2923634: [PP-1] Use hook_theme_suggestions in views has been applied).
One hint can be array_slice() returns an array, so we are searching for an array within the suggestions (flat) array. That's always FALSE. If we just want last element of the array, array_pop is a better alternative?
Also I can't comment on the correct solution from a Theme / Twig prospective. I can see from the twig.engine a big chunk of code has been removed about 'theme_hook_suggestions'. #23 reported "Attempts to redetermine the suggestions and print these as the file name suggestions.", but maybe a bit more details?
We do need some test coverage. :(
Comment #41
jwilson3Comment #42
markhalliwellComment #44
mdolnik commentedPotentially related issue:
Base theme hooks are executed in the incorrect order
Comment #45
thomas.frobieterAfter patch #33 is applied, all file override suggestions in the twig debugging comments are lost in our case.
Comment #46
anybodyAdditional information and workaround... I'm not sure if this is the same problem / reason, but it seems it could be...
All container suggestions are having the wrong order:
As you can see the more specific suggestions are at the bottom (excluding container.html.twig) while they should be at the top.
Patch #5 didn't solve that for us and I couldn't find the place where these suggestions are built. I was looking for something like "..._suggestions_container()" in core but it seems to be a more general logic?
As quickfix we now used
but of course this shouldn't be required and is DANGEROUS if the reason / bug is fixed... because then we'd create the wrong order here.
(So we created a little messy detection:
The result is
which is correct.
Does this issue address this problem? And if yes, why doesn't #5 solve it? (Add a test for that?)
Comment #47
aaronmchaleI'm guessing this is also what is happening to CSS files where multiple levels of sub-themes/base-themes are used, where some CSS files are loaded in the wrong order breaking some styling.
Order should be:
theme1
theme2
theme3
theme4
Order actually is:
theme1
theme3
theme2
theme4
Update: in the libraries.yml file, if you set the weight of the CSS (e.g. assets/theme.css: { weight: 1 }) it seems to have an effect, I wonder if this is some kind of edge case where the CSS files that are loading in the wrong order are doing that because they have the same name?
Update2: the naming doesn't seem to matter, issue still happens, so essentially a workaround is using weights but since this might not always be practical so this looks like a bug.
Comment #48
markhalliwell#47 has nothing to do with this issue.
That being said, the "issue" you're experiencing is due to how Drupal 8 now handles assets (via libraries). All you need to do is add dependencies to your theme libraries. Doing this will automatically ensure they're loaded in the correct order. You don't have to manually fiddle with weights (which can no longer be positive integers anyway).
Comment #49
aaronmchale@markcarver thanks for the input, that seems to work, strange that the order isn't correctly simply by setting the base theme
Comment #50
markhalliwellStill off-topic, but figured it'd be easier to just respond here.
It cannot and likely never will due to the general complexities of how libraries (and their dependencies) function.
The idea behind libraries is that the developer should know what the libraries intentions are and define them accordingly, manually (once).
How would Drupal know that the 3rd library defined in your theme should be dependent on the 5th library defined in the base-theme?
Is it supposed to just assume (which is never good) that maybe it's perhaps just the first library defined in each that should be linked? That too would need additional documentation as well to handle this "magic" association. What if this dynamic association isn't wanted, one would have to alter the library they just defined to remove it.
Also, simply making all libraries dependent on all the base-theme libraries wouldn't work either. What if one of the libraries is a framework and needs to be loaded before anything else, including a base-theme?
---
I think the confusion around libraries stems from the fact that most simple sites/themes do "operate" in the perceived fashion of "automagic dependencies" due to how Drupal loads things only as they're needed. Assets are generally added in a FIFO order and when the workflow of assets are simplistic in nature like this, that's usually what you get.
That being said, if an extension does any complex library handling, like alters (e.g. a module like
advaggor a base-theme that dynamically adds in an external framework likebootstrap), the weight in which these assets are actually loaded can sometimes get skewed.Libraries are, for the most part, a self-contained system/hierarchy unto themselves. They don't really know the top-level Drupal add/load order, just that they were given an asset without dependencies. So unless you give them proper dependencies, the library asset handler doesn't really have a clue as to how best handle them; it just spits it out when and where ever it can.
The easiest solution to "fix" this is to quite simply always be explicit about which libraries your library depends on. Then there's no confusion, for anyone involved.
Comment #53
bkosborneRE: #47 - #50, someone had opened an issue relating to this and I just cleaned it up: #3070381: Base theme libraries may be output in reverse order. Mark is right though, the "fix" is to just properly understand how the library dependency system works.
Comment #54
luke.stewart commentedI'm still seeing the behaviour as originally described on 8.9.0-beta2.
This is for a site using a subtheme of bootstrap_barrio -> bootstrap_sass. The use case is including the same menu twice on the page and attempting to format it differently depending on the block it is in.
The patch applies cleanly to 8.9.0-beta2.
The patch appears to resolve part of the bug in that the order of the template suggestions as output by twig debug appears to be correct but the more specific one is being selected.
Before:
After:
I've only noticed this behaviour for menus.
I'm not seeing behaviour described in #45.
The work around suggested in #46 didn't work. menu--main.html.twig still got added at the start.
Comment #56
joseph.olstadpatch still applies to 9.0.x - Triggered tests
patch still applies to 9.1.x - Triggered tests
patch still applies to 8.9.x - Triggered tests
patch still applies to 8.8.x - Triggered tests
we still need this, trying to get our patch list down to a more manageable number, would be nice to nail this one, doesn't look like much work is needed to get this in.
see comment #40 for some nit picking todo changes
#2752443-40: Incorrect order and duplicate theme hook suggestions
Comment #57
ofrommel commentedI am having the same problem with Drupal 8.9.1 and the Bootstrap Radix theme:
You can see I also made up some template suggestions to test specificity but no matter what always the same template gets picked (which is in the list twice). I also tried the patch but it didn't change anything.
Comment #59
johnalbinFYI, the latest MR in #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme may fix this issue at the same time.
Actually, looking at this closely, I see that Drupal core's
views_theme_suggestions_container_alter()is implemented incorrectly; the return values of buildThemeFunctions() should be reversed before merging them with $suggetions. So that should be fixed in this issue.Comment #60
joseph.olstad@JohnAlbin, thanks for this note, I was struggling with views theme functions and suggestions this week for a custom module, I will have a look at that merge request #2118743 .
Comment #61
johnalbinI went ahead and split off the Views more link container bug into its own issue since it is so self-contained. #3188122: Views more link container theme suggestions are in the wrong order
And, yeah, the MR in #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme definitely fixes this issue at the same time. Looking at the last patch in this issue, I can see that the approaches are very similar; moving all the code in twig.engine into ThemeManager.php.
Comment #62
anybody@JohnAlbin, thank you very much for the progress and impressive work on the other issues. So if the problems documented here are represented in the other issues tests (I didn't have the time to check that yet), I guess we can close this one as duplicate and link them for reference?
Comment #65
larowlanCame here from #2994975: Base theme hooks are executed in the incorrect order which is similar but different.
can we split this into multiple assignments, its hard to understand what this is doing and we generally avoid this kind of assignment in core
it would be good to put this into a variable to convey what it represents, would make it easier to read.
e.g. $derived_suggestions_without_original_hook
we call array_slice($derived_suggestions, 0, -1) twice here, for performance but more-so for readability, I think it would be good to assign this to a variable that conveys what this represents.
e.g. $derived_suggestions_excluding_base_hook
Nit needs a trailing . here
same here this could be $derived_base_hook, rather than call it twice
Comment #66
ravi.shankar commentedAddressed comment #65, please review.
Comment #67
star-szrComment #68
aaronmchalePatch in #66 failed testing, so status remains at needs work.
Comment #69
star-szrI have yet to see any test results, so tried to requeue.
Edit: It's just saying build successful, maybe this is a new thing, I'm used to seeing a pass/fail here in the issue. Clicking through to Jenkins I see that there are failing tests.
Comment #70
joseph.olstadre: #66
From the test runner logs:
Comment #71
aaronmchaleMy understanding is that if there are too many fails it will default to "Build successful".
Comment #72
yogeshmpawarUpdated patch will fix build/failed test issue
Comment #73
ranjith_kumar_k_u commentedFixed CS error
Comment #76
anthony thomasFor me, order of template suggestions still wrong.
Edit #73 patch to fix this
$suggestions = array_merge($derived_suggestions_excluding_base_hook, $suggestions);Comment #77
ravi.shankar commentedAdded reroll of patch #76 as it's not getting applied.
Comment #80
nicxvan commentedI created a related issue since this seems to happen at the page template level too. The patch here does not resolve the page level template issue so it probably makes sense to track separately: https://www.drupal.org/project/drupal/issues/3314943
Comment #81
greggmarshallIt would appear this patch and the latest one from #2118743: Twig debug output does not display all suggestions when an array of theme hooks is passed to #theme conflict with each other.
Comment #82
ollu commentedPatch #73 applies and the output does not contain any duplicates though suggestion added via code does not get picked up by system and by that failing.
FILE NAME SUGGESTIONS:
* input--textfield-site-search.html.twig (*)
* input--textfield.html.twig
x input.html.twig
(*) Added via suggestion hook and is not used despite being present in template folder for the current theme.
Comment #83
ameymudras commented#77 wasn't getting applied to 10.1.x, I have re-rolled the above patch. Couldn't generate the interdiff
Comment #86
stomusic#77 wasn't getting applied to 10.1.0, #83 also. I've make re-roll
Comment #87
thomas.frobieter#86 doesn't work well for me, admin menu bar suggestion comment (as an example, the error appears multiple times for different templates):
Comment #88
jacobbell84 commentedI also experienced the same error from this patch. I think the patch has a couple different issues. First, it looks like a lot of the derived suggestion logic was pulled from the twig.engine debug code, but the problem with that is that the debug output is presented in reverse order.
This would generate hooks in the order of
base_hook__specific__really_specific
base_hook__specific
base_hook
When the later code merged this array with the suggestions array coming from the theme system (which is in the opposite order) it would create odd sorting under some conditions.
Second, the patch had this check:
The above code would always fire since array_slice returns an array not a scaler value, which could sometimes cause duplicates.
Third, part of the updates removed some variable initialization in twig.engine
Later in the twig.engine file, the base_hook variable is used to determine whether a suggestion is valid or not
That's the reason folks started getting the "INVALID FILE NAME SUGGESTIONS:" error after applying the patch. I made a new patch that addresses those 3 issues.
Comment #89
smustgrave commentedSeems to have failures and is missing test coverage. Moving to NW for that.
Comment #90
jacobbell84 commentedAttempting to fix the failures. I assume we'll want to wait until it's confirmed this is the approach people want before we write test cases though.
Comment #91
jacobbell84 commentedFixing failing unit test.
Comment #92
joseph.olstadComment #93
joseph.olstadActually, still needs tests.
Comment #94
jacobbell84 commentedYup, I just wanted to fix the issues first. I'll try to get a unit test going, but I have very little experience with it so it might take a bit.
Comment #95
nicxvan commentedThis should probably move to an MR, the core team is using MRs for development now and the test suite is significantly faster on gitlab if you're writing tests.
Comment #97
nicxvan commentedI've converted the patch in 91 as closely as I can to 11.x, there was a refactor in https://www.drupal.org/project/drupal/issues/2953921 that may have affected how this works. I have not added any additional tests, but I will review the MR now to see if it is working.
Hiding patches.
Comment #98
nicxvan commentedComment #99
nicxvan commentedCan someone confirm this is still an issue on 11.x
I was unable to reproduce this, if you can update the steps to reproduce I'm happy to continue testing.
Comment #100
joseph.olstad@nicxvan, the WxT distribution has been using patch #1 for several years.
With that said, we're using the bootstrap 3x theme which may not behave exactly as the core themes. It would be good to try the latest version of this patch and give it some serious looks.
Unfortunately I don't have any spare cycles at this moment.
Comment #101
nicxvan commentedThere was some refactoring in the same area so I think that might have resolved this issue, but I'd like another confirmation.
Comment #102
ayalon commentedThanks for the updated patch. Here is an updated patch file for use with Drupal 10.2 based on the merge request usable with composer.json
Comment #103
joseph.olstadphplint saw an undefined variable, replaced with what looked to be obviously the correct variable.
Comment #104
alphex commentedI can confirm this is still happening with Drupal 10.2.5 - WITH - the patch from #102 applied.
I would expect that "page--node--2.html.twig" would be at the top of the list.
----
When I add some code I've used in past sites, to my .theme file
It puts the template suggestion, in the right spot, but the TOP one is still there, which is wrong.
Comment #105
sapetm commentedSorry, bad patch file, please disregard.
Comment #106
sapetm commentedSorry, bad patch file, please disregard.
Comment #107
sapetm commentedSorry folks, third time's the charm, or something like that. I uploaded the wrong patch file with my other two comments. This is the patch I am using for Drupal 10.2.6 and PHP 8.1.27. It is identical to the patch in comment #102 but with the addition of an array_unique() in the second hunk when setting the value of the $suggestions array in the render function. This fixes the issue for us. Hope it helps!
Comment #108
nicxvan commentedCan you please add those changes to the merge request? People can then generate local patches as needed and the core team uses the actual mr for testing and merging.
Comment #109
scott_euser commentedLooks like the issue summary needs an update? Drupal 11 with default Olivero theme, no changes from clean install other than turning on twig.config debug to true now results in this which appears correct:
The selected customisation comes from olivero.theme:
For the region 'primary_menu'. Is there a step I am missing to reproduce?
Comment #110
djroshi commentedI'm going to post this as it might help someone who stumbles over this issue (as I did). This is using Drupal 10.2.6 with Bootstrap5 subtheme.
When placing a menu block in a region (pretty normal thing to do) I get the following suggestions, prioritized first to last (as suggestions are array_reversed)
1. menu__region-name
2. menu__menu-name_region-name
3. menu__menu-name
This is counterintuitive because (in my mind at least) theme suggestions should be ordered from most specific to least specific i.e.
1. menu__menu-name_region-name (that menu when it appears in that region)
2. menu__menu-name (all instances of that menu)
3. menu__region-name (all menus in that region)
Can someone perhaps confirm if this is happening on other installs of Drupal? Or is it just me :D
Comment #111
anybodyRe #110 you're right and that's what this issue is about.
We're still experiencing this with Drupal 10.3.0, so I don't think this is fixed without this patch.
Update: re-tried the MR and it seems it works correctly for us.
Duplicate entries are gone and the Twig Debug Theme suggestions output is now ordered correctly! Drupal 10.3.0
Comment #112
anybodyComment #113
dinesh18 commentedIs there a fix for this?
Comment #114
welly commentedI've tested the patch at #107 on Drupal 10.4.5 and confirm this works. It fixed an issue I was having that was exactly as described. This was after an upgrade of group_content_menu from 3.0.1 to 3.0.5 and Drupal 10.2.12 to 10.4.5.
Comment #117
xjmPer @lauriii in #30, this was triaged by
Adding triage credits.
Comment #121
volegerAdded link to #1685492: Convert theme engines into services as the theme engine location was changed.