Problem

Components! fails to discover templates from the primary theme when "use admin theme" is enabled and admin theme is active.
For example, when editing a view that displays rendered content.

Proposed Resolution

During namespace resolution and template discovery, include both the admin theme and primary theme.

Remaining tasks

  • Update discovery mechanism in Components Registry
  • Reviews
  • Tests
  • Change record (is this necessary for beta releases?)

User interface changes

none

API changes

ConfigFactoryInterface argument added to Drupal\components\Template\ComponentsRegistry constructor and service definition.

Data model changes

none

Symptom

Fatal errors like
Twig\Error\LoaderError: Template "@organisms/header-top/header-top.twig" is not defined in "themes/custom/aedt_theme/src/templates/layout/region--header-top.html.twig" at line 9. in Twig\Loader\ChainLoader->getCacheKey() (line 142 of vendor/twig/twig/src/Loader/ChainLoader.php).

Steps to reproduce

  • Define a component namespace in your theme
  • Create a page template that embeds another component using that namespace
  • Login as a user with permission to view the admin theme (but not user 1)
  • Setup a custom 403 page
  • Edit a node you don't have permission to edit

Expected behavior

View the 403 page.

Observed behavior

Fatal error described above.

This issue persists even after the component definition has been updated with the 3.x API changes.

Here's an example component library definition:

components:
  namespaces:
    organisms:
        - src/_patterns/03-organisms

And this is how the region--header-top.html.twig file looks like:

{% if content %}
  {% include '@organisms/header-top/header-top.twig' with {
    'content': content,
    'attributes': attributes
  } %}
{% endif %}

Issue fork components-3107993

Command icon 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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

inge_dt created an issue. See original summary.

capysara’s picture

Not related to this specific module, but adding directory and path to the include statement as noted here worked for me: https://www.drupal.org/project/drupal/issues/2817553#comment-13820148

tobiberlin’s picture

I found the same error - everything worked before the update but for me it was the update from Drupal core 8.9.3 to 8.9.6 or the update from Components version 1 to version 2... I am not sure yet because I did these updates in parallel.

The solution from the linked comment is not really a solution as the idea of the "'@organisms/header-top/header-top.twig'" syntax is that it is working independently from the current twig template files location.

tobiberlin’s picture

For me I found a solution: The component was defined in a theme but the template file which used the component was defined in a module. This module's template file was rendered within another theme. When I moved the component definition and the component files to the module everything worked. Strange that this worked before...

JohnAlbin’s picture

Category: Bug report » Support request
Status: Active » Postponed (maintainer needs more info)

There's not enough information for me to figure out what is going on.

JohnAlbin’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)

I'm closing this since I don't have enough details (like directory paths) to help solve this issue.

Please re-open if you want to provide more details.

garypigott39’s picture

Ok so we also had this issue; the scenario we had was we were using several themes including the emulsify theme where we had a definition for assorted namespaces. Now these werent being picked up in Node edit and we received the aforementioned template not found error.

Looking at the ComponentsLoader class we could see that setActiveTheme() was loading all module based namespaces but was ignoring any theme names identified by `$theme_info = $this->componentsInfo->getAllThemeInfo();` the solution for us was to add the following just after the theme_info variable was set

    // Add theme info (theme names) to active themes.
    if (!empty($theme_info)) {
      $active_themes = array_unique(array_merge($active_themes, array_keys($theme_info)));
    }

This then ensured that the namespaces were picked up.

The other alternative which also worked for us was to add the namespaces to any module's info file.

This was in version 8.2.4 of the module

larowlan’s picture

Issue summary: View changes
Status: Closed (cannot reproduce) » Active

Added steps to reproduce into the issue summary

Hit this when updating from 8.9.16 to 9.2.0 and from components 1 to 2

larowlan’s picture

Category: Support request » Bug report

Reclassifying this as a bug report for now, as it definitely relates to active theme switching mid request

larowlan’s picture

Version: 8.x-1.1 » 8.x-2.x-dev

Looking at core, there's been no changes to ThemeManager's handling of setting/resetting active theme since 2015

ipwa’s picture

Status: Active » Reviewed & tested by the community

I was getting the following error:
Twig\Error\LoaderError: Template "@molecules/announcement/_announcement.html.twig" is not defined in "modules/custom/announcement/templates/announcement.html.twig" at line 19. in Twig\Loader\ChainLoader->getCacheKey() (line 142 of /var/www/html/vendor/twig/twig/src/Loader/ChainLoader.php).

Same sort of situation:

  • Namespaces defined in theme
  • Namespace used in custom module entity template
  • Started getting error after upgrading the Components module from 1 to 2
  • Get error when accessing entity using admin theme

The patch in #7 fixed things for me, thanks Gary!

JohnAlbin’s picture

it definitely relates to active theme switching mid request

Huh. I tried to delay the check of the active theme until the very last moment because I knew Drupal switches active theme mid-request sometimes. But it seems it still wasn't enough? Maybe this is a core bug too? Regardless if its a core bug, we'll add a work-around in this module for the issue.

Lee, thanks for helping me to recreate the issue.

I'll try to take a look at this issue in more detail in the next week.

larowlan’s picture

Thanks John
I found another way to replicate this, but its probably my fault.

I've got a module, which has a twig template that references a template from the theme, via the theme namespace.

I've got paragraphs setup on the edit for using a preview-view mode to show a preview of the item before editing.

This invokes the template from the module, which tries to load the theme namespace. But the theme isn't active because I'm editing a node, so its using the admin theme.

Probably falls under 'you're doing it wrong' but might make it easier to reproduce for testing sake.

larowlan’s picture

For others in the same misfit boat as my description above, just referring to the theme namespace from the profile info file and setting the protection flag in the them was enough to resolve this default vs admin theme issue (albeit by hacking around it)

Kasey_MK’s picture

Thank you, #7 worked for us too. We fiddled a lot with the components namespaces syntax in our theme info.yml and in our twig files but nothing was working after upgrading to Components 2 on 8.9.16

pixelwhip’s picture

I was running into this error using Layout Paragraphs in conjunction with UI Patterns and the Components module. I would get this error when editing a node using the admin theme that contained content in the form of Paragraphs that were themed with UI Patterns which were defined in the front-end theme where they referenced a template via a component namespace also defined in the front-end theme.

The patch from the above merge request resolved the issue for me. https://git.drupalcode.org/project/components/-/merge_requests/28.patch

JohnAlbin’s picture

Title: Template is not defined error » Template is not defined error on node edit / admin pages
Status: Reviewed & tested by the community » Needs work

So, the patch in #7 breaks tests.

Specifically, the patch casually merges all theme namespaces into the namespaces of the active theme (or at least what Drupal is reporting as the active theme). That behavior is potentially a regression for the following issues: #3027672: Any other theme can override the active theme's component-libraries, #3080827: Base and sub theme hierarchy is not taken into account

The tests aren't particularly good in 8.x-2.x (they were refactored in 3.x), but they are sufficient to show that the failing test expects that only the namespaces defined by the active theme, its base themes and modules are to be available. The active theme should not be allowed to use namespaces of some random other theme that is not in its base theme lists.

As I said in another issue: "its weird that a theme could define a dependency on another theme that is not in its base theme list and that the theme would define that dependency deep inside a Twig template and not in the .info.yml and .libraries.yml files where all the other dependencies are defined." I stand by that statement. Letting a theme have a hidden dependency is a really bad idea.

However, as previous comments have shown, we need to make an exception for the admin theme; it should be allowed to see the namespaces of the default theme. We should also consider if the admin theme will be allowed to see the namespaces of all installed themes. I'm not sure. I'd lean towards "no", but I'd listen to counter arguments.

So, as I understand the issue now, the proper fix for this issue would be for the admin theme to have the default theme's namespaces be available.

JohnAlbin’s picture

Priority: Normal » Major

Considering this affects core modules like layout builder (when the admin theme is active for the edit layout page and the layout components are in the frontend theme), this is kind of a big deal. Bumping the priority.

zezeze’s picture

I believe I have an issue related to this. We just updated our Drupal core to 9.2.7 from 8.9.2 and we are using Components 8.x-2.4.

My components are located in root/vendor/cfaes/cfaes-components and the components declaration is:

components:
  namespaces:
    cfaesComponents:
      - ../../../vendor/cfaes/cfaes-components/dist/components

Many of my custom modules use the @cfaesComponents namespace with no problem and if a view template (in a custom module) is utilizing a component from the theme I can see it rendered in the view as well as the view preview.

However after the upgrade to 9.2.7 my custom modules that utilize my theme's components in overridden views templates fail to render in the view preview (but still render when viewing the page where the view is being used).

When editing a display in a view I get the following error:

Error location: /admin/structure/views/view/events/preview/block_2?_wrapper_format=drupal_ajax

Twig\Error\LoaderError: Template "@cfaesComponents/lists/rows/standard/list-standard.html.twig" is not defined in
"modules/custom/cfaes_event/templates/views-view-list--events--block-2.html.twig" at line 2. in Twig\Loader\ChainLoader->getCacheKey() (line 98 of /usr/local/webs/faes-d8/htdocs/vendor/twig/twig/src/Loader/ChainLoader.php).

Note: After reading #4 I took the same component definition from the theme and placed it in the custom module as well and boom, the view preview works. Is this how it should be (I swear before the update my view previews were able to sort out where the components were).

ctrlADel’s picture

The use case that brings me here is an outlier I'm sure, I have a custom layout deriver that creates layouts based on json definitions which contain namespaced template paths. I noticed recently that after a cache rebuild if the first page I hit is an admin page then an error is thrown when trying to access the front end Twig\Error\LoaderError: Template "modules/custom/custom_layouts/@templates/section/two/two-column.html.twig" is not defined. but if a frontend page is hit first after cache clear then everything works fine.

We should also consider if the admin theme will be allowed to see the namespaces of all installed themes. I'm not sure. I'd lean towards "no", but I'd listen to counter arguments.

I think the capability to merge all installed theme namespaces into the admin theme needs to at least be possible if not on by default. While most sites will have just one default theme the active theme is negotiated by ThemeNegotiators and can change dynamically when one is implemented. In the situations where more than one theme is in use a disclaimer/note that the site is responsible for avoiding namespace collisions seems fine.

tjh’s picture

Running into this while using Components and a custom theme that is extending Claro. This theme is acting as both the admin & default theme, so it handles admin routes as well as node view pages for proofing content. The actual front end of the website is decoupled.

Drupal version: 9.3.9
Components version: 2.4

My component templates are available at themename/dist/components/ e.g. themename/dist/components/alert/alert.twig

My themename.info.yml file:

base theme: claro

... a bunch of extended and overridden libraries ...

components:
  namespaces:
    cmsds: dist/components

Referencing a component in a theme template (status-messages.html.twig):

<div data-drupal-messages class="messages-list">
  {# Pass variables from Drupal through to our design system components #}
  {% for type, messages in message_list %}
    {% include '@cmsds/alert.twig' with {
      attributes, type, messages, status_headings, title_ids
    } %}
  {% endfor %}
</div>

It also fails if I reference the complete path to the template, e.g. @cmds/alert/alert.twig

Error:

"Twig\Error\LoaderError: Template &quot;@cmsds/alert.twig&quot; is not defined in &quot;themes/custom/themename/templates/misc/status-messages.html.twig&quot; at line 34. in Twig\Loader\ChainLoader-&gt;getCacheKey() (line 98 of vendor/twig/twig/src/Loader/ChainLoader.php)."

The namespace is not defined for either admin or regular routes. Expected behavior would be that the namespace defined by theme & used only in that theme's templates would be available regardless of admin/default theme. It is both and yet namespace is undefined for either.

Can also the confirm that the patch in #7 did not work for my use case. Nor did moving the components namespace to a module .info.yml instead of the theme.

Edit: Also tried Components version: ^3.0@beta and the same error is present

tjh’s picture

Follow up to my last comment... I forgot to enable the module! Ha! I added to composer but never ran `drush en components` afterwards.... Doing that, it works as expected with admin themes and 3.0@beta . Very silly mistake on my part. Thanks for the excellent module!

JohnAlbin’s picture

So I dug into the code. In both 8.x-2.x and 3.x, the Components module simply reads the current theme using \Drupal\Core\Theme\ThemeManager->getActiveTheme() and the internals of that method are using \Drupal\Core\Theme\ThemeNegotiator. So it feels like the Components module is doing things "the right way". But obviously, it's failing to see the active theme has changed when inside a subrequest.

Does a subrequest not tell the ThemeManager that the active theme has changed? Or is there a different ThemeManager inside the subrequest?

Right now, Components module gets the ThemeManager via dependency injection. Do I need to grab the ThemeManager from \Drupal::service('theme.manager') instead?

I'm not sure when I'll get to test this theory, but I'll post back once I have. Unless someone beats me to it. :D

Kris77’s picture

Patch #7 is not applicable with last 3.0@beta.

AaronBauman’s picture

Version: 8.x-2.x-dev » 3.x-dev

Issue persists into 3.x, and neither existing patch nor MR apply.
Not sure how to reroll, because it seems to have been entirely rewritten.

AaronBauman’s picture

Any updates here?

AaronBauman’s picture

@JohnAlbin I don't think grabbing theme manager from \Drupal::service() will make a difference
ThemeManager is instantiated at the beginning of the request, and its defaultTheme property is statically initialized only once.

So in order to get the proper theme on a sub-request, we need to re-instantiate Drupal's ThemeManager service every time prior to calling getActiveTheme().
IMO this seems like a terrible waste of resources, and worthy of a fix in core, if this is indeed what's happening.

In my case - views preview of rendered content - I don't think a sub-request is involved.
A view is edited using admin theme, and views preview attempts to render the preview in admin theme.
But to render the entity we need a template defined in the default / non-admin theme, which is not available and thus the error.

AaronBauman’s picture

Assigned: Unassigned » AaronBauman

Opened new MR against 3.x https://git.drupalcode.org/project/components/-/merge_requests/32

First commit is test only, to demonstrate the issue.

Subsequently, I will update with the patch that's working for me.

AaronBauman’s picture

Status: Needs work » Needs review

OK, so comment #28 TEST ONLY demonstrates the bug.

And the MR addresses the bug thusly:
- If a given template is not found in the current active theme, and the active theme is not the default theme, also check the default theme.

This change requires adding ConfigFactory to dependencies, so that we can grab the active theme.
If we think it's better to check ALL enabled themes, we could do that through ThemeExtensionList without adding any new dependencies.

ironsizide’s picture

The fixes in MR 32 are working for me nicely in Drupal 9.5.9.

sanoopuio’s picture

I get this error on 3.0.0-beta3, not sure how to continue

Sana.Neyazi’s picture

Hi @aronbauman, Could we know when we can expect Drupal 10 stable release of component module?

AaronBauman’s picture

Assigned: AaronBauman » Unassigned

No commits on this project and no comments from maintainers for over a year 😬

Dunno what's happening but that's not a good sign.

Yujiman85’s picture

I had the same issue with templates not being defined in Twigs using "extends" after the update to the latest version. It seems I was able to fix the situation by updating the namespaces in the info.yml file for my custom theme from the old API to the new one as per https://www.drupal.org/docs/contributed-modules/components/registering-twig-namespaces. Not sure if this will work for anyone else but worth a shot if your situation is at all similar.

Old:

component-libraries:
  [THEMENAME]:
    paths:
       - components 

New:

components:
  namespaces:
    [THEMENAME]:
      - components

So far I haven't run into any breaking issues but if I do I'll come back to update

sanoopuio’s picture

Thanks for hint, it works . https://www.drupal.org/docs/contributed-modules/components/registering-t...
# This example YAML creates 3 namespaces: @atoms, @quarks, @universe

components:
  namespaces:
    # If your namespace only has one directory,
    # you can use this simple YAML syntax.
    atoms: library/atoms
    quarks: library/quarks
Abhinand Gokhala K’s picture

Solution #36 worked for me. Thanks.

thalles’s picture

Status: Needs review » Reviewed & tested by the community

Works fine to me!

Yujiman85’s picture

Status: Reviewed & tested by the community » Closed (works as designed)

Since this technically works like it's supposed to after changing how the namespaces are structured, I'm going to move this over to "Closed (works as designed)". If that isn't right someone please move it back. The documentation for the API is there but it's two clicks deep from the module page, maybe there could be a more noticeable section highlighting how to structure the namespaces? Especially now since the old way doesn't seem to work after moving to v3.

AaronBauman’s picture

Title: Template is not defined error on node edit / admin pages » Template is not defined error on admin pages when using administration theme
Issue summary: View changes
Status: Closed (works as designed) » Reviewed & tested by the community

I don't think this should be closed, as this issue persists even for themes whose namespace definitions have been update for the new API.
This is not a problem with implementations, this is a problem with Components! module's discovery system.

The current MR includes a test to demonstrate the bug per comment #28, as well as a resolution for it.
Issue summary updated and set back to RTBC

kekkis’s picture

RTBC +1. Created a local patch from MR in #28 and it fixes our problem which is exactly what the test describes.

dgroene’s picture

Please ignore- did not realize the merge request was already against 3.x... and I cannot delete the file now...

dgroene’s picture

dgroene’s picture

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 45: components-template_undefined_on_admin_pages-3107993-45.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

dgroene’s picture

raywalters’s picture

Applying the merge request patch in this issue along with the merge request from https://www.drupal.org/project/ui_patterns/issues/3335833 for ui patterns resolved my issue. Twig\Error\LoaderError: Template "modules/contrib/ui_patterns/templates/pattern-teaser.html.twig" is not defined. in Twig\Loader\ChainLoader->getCacheKey() (line 10 of /var/www/html/docroot/modules/contrib/ds/templates/ds-entity-view.html.twig).