Dripyard Premium Drupal Themes: How an unclosed broke Drupal’s JavaScript

A quick search later, and there it was. One lonely, unclosed <em>. I properly closed the tag, reloaded the page, and everything immediately started working again.So, I go into the console and type drupalSettings (fun fact, you can do this on any Drupal site).That <em> tag does not exist in the page source. But it does exist in the DOM. This is the important distinction. The DOM is not the same thing as the raw HTML. If you leave an HTML tag unclosed, the browser will do its best to fix things for you. Sometimes it guesses wrong.

The problem

What made this extra confusing was that it only happened on this one page, and only for this one theme.It’s RIGHT THERE! What’s going on here?That’s when I saw the problem. drupalSettings.path was undefined.Theme settings page with tons of JavaScript errors in the console.

Process of elimination

The errors wereYou can actually see the moment it went sideways here. This is the story of how I tracked it down.That was me earlier this week while trying to figure out why Drupal’s JavaScript was completely broken. But only on one page. And of course, this happened during a live demo!drupalSettings is how Drupal passes data from PHP to JavaScript. It does this by embedding a JSON blob inside a <script> tag right before the closing </body>.Takeaways:Sometimes you hit a bug and your brain just goes, “huh.”

Theme settings page with only two errors in the console.

Zero results.Uncaught TypeError: Cannot destructure property 'permissionsHash' of 'drupalSettings.user' as it is undefined. at contextual.js?v=11.3.2:22:11

Uncaught TypeError: Cannot read properties of undefined (reading 'currentQuery') at Object.attach (active-link.js?v=11.3.2:25:47)

Debugging (with a quick how-to)

I’ve seen this before. The DOM can get mangled up if there’s an unclosed HTML tag somewhere in the markup. And if you look at the selector that drupalSettingsLoader.js is using, the <script> needs to be a direct descendant of the <body> tag.I uninstalled BigPipe.I viewed the page source to double-check, and sure enough, the drupalSettings script was right there in the HTML.

Sources panel of DevTools showing the debugger stopped within active-link.js

Normally the console points you directly to the problem. This time it didn’t. So I went into full process-of-elimination mode.

What’s drupalSettings?

I scrolled down in the Elements panel to where the drupalSettings script lived. And there it was wrapped inside an <em> tag!Now that I knew what I was looking for, the fix was straightforward.

 Developer Tools console with drupalSettings typed in showing an empty object

To do so, I clicked on the link to active-link.js and set a breakpoint by clicking the line number. I know the breakpoint is set, because the line number is highlighted with a blue flag. I then reloaded.Dripyard adds a bunch of options to our theme settings pages. On one particular theme, Great Lakes, the settings page was loading with JavaScript absolutely wrecked.

View of the source code with the drupalSettings script highlighted.

/**
* @file
* Parse inline JSON and initialize the drupalSettings global object.
*/

(function () {
// Use direct child elements to harden against XSS exploits when CSP is on.
const settingsElement = document.querySelector(
'head > script[type="application/json"][data-drupal-selector="drupal-settings-json"], body > script[type="application/json"][data-drupal-selector="drupal-settings-json"]',
);

/**
* Variable generated by Drupal with all the configuration created from PHP.
*
* @global
*
* @type {object}
*/
window.drupalSettings = {};

if (settingsElement !== null) {
window.drupalSettings = JSON.parse(settingsElement.textContent);
}
})();

I saw that the settingsElement variable is set to the following CSS selector:This was definitely a “huh” moment, but I kind of love bugs like this.At this point I needed to see how drupalSettings actually gets loaded. Most of Drupal core’s JavaScript lives in /core/misc, and sure enough, there’s a file called drupalSettingsLoader.js.I set a breakpoint at line 23, to see if it the object was loaded. Sure enough it did not. The loader script couldn’t find the <script> tag it was looking for.

Dev tools JavaScript debugger stopped on drupalSettingsLoader.js, showing an empty object

Also, maybe do not do a live demo after making changes to your code..head > script[type="application/json"][data-drupal-selector="drupal-settings-json"], 
body > script[type="application/json"][data-drupal-selector="drupal-settings-json"]

Nope. Still broken. But, at least the console was quieter now.

Elements panel scrolled down to show the drupalSettings script inside of an <em> tag” class=”image-style-wysiwyg-content”></p>
<h2>The real culprit</h2>
<p>This file is about as straightforward as they come.It was empty!! What the hell?!We inject a little JavaScript for the color selector, so that was the first thing I nuked. I commented out all of it. No change.Totally broken. No behaviors. Console full of errors. Not ideal when people are watching you.</p>
<h2><strong>Finding the mistake</strong></h2>
<p>The browser will pause execution of JavaScript at that point and I could now inspect the variables.</p>
<ul>
<li data-list-item-id=It only happened on Great Lakes

  • We do not use many <em> tags
  • I started looking at active-link.js first to see what’s breaking.

    Code editor showing the mistake

    So what did we learn?

    Next I noticed a wall of BigPipe-related errors. Aha moment. BigPipe recently switched to HTMX. Surely this was a core bug, right?This was the problem. Because of the unclosed <em> tag mangling the DOM, drupalSettingsLoader.js couldn’t find the drupalSettings <script> tag.

    • Simplifying the problem is huge. Removing our JS and BigPipe helped narrow the search fast
    • DevTools show you the DOM, not the original HTML. That difference matters
    • Knowing how Drupal works helps you debug faster and with more confidence
    • Even tiny markup mistakes can have massive side effects

    Through testing, I knew that this only happened on one page, and for one theme (Great Lakes).

    Similar Posts