Skip to content

Logo palette observer can throw html.getAttribute is not a function after a global collision #4541

Description

@pirate-bot

Summary

When the logo palette behavior is active, a frontend attribute change can produce Uncaught TypeError: html.getAttribute is not a function if another script has replaced the page-global html value.

Expected behavior: Theme logo palette handling completes without a JavaScript exception when other frontend plugins are active.

Actual behavior: The reported guest workflow throws the exception from neve-script-js-after. A Fluent Forms submission also returns Unauthorized in the same workflow, although the available evidence does not establish that the Neve exception causes that response.

Impact: On the reported site, guest form submissions fail while logged-in submissions reportedly work. The confirmed Neve impact is the frontend JavaScript exception; the form-submission impact remains to be isolated.

Customer context

  • Product / area: Neve theme, Header/Footer Builder logo palette behavior; Neve Pro is active but the implicated code belongs to the free theme repository
  • Version: Not provided
  • Environment: WordPress site; failure reported for logged-out visitors only
  • Integration / third party: Fluent Forms
  • Reported error / symptom: Uncaught TypeError: html.getAttribute is not a function in neve-script-js-after; form request reports Unauthorized
  • Impact: Guest form submissions reportedly fail; logged-in submissions reportedly succeed

Reproduction notes

Reported workflow:

  1. Visit a page containing a Fluent Forms form while logged out.
  2. Submit the form.
  3. Observe an Unauthorized result and Uncaught TypeError: html.getAttribute is not a function from neve-script-js-after.
  4. Repeat while logged in; the customer reports that submission succeeds.

This workflow was not independently reproduced. Source inspection provides a narrower deterministic hypothesis: after Neve initializes its logo palette observer, replacing window.html with a non-element and then mutating an attribute on document.documentElement reaches the exact failing dereference. The ticket does not identify which script performs that assignment or establish that the exception causes the authorization response.

Diagnosis

Conclusion

The Neve logo palette inline script exposes html as a mutable page-global variable and dereferences it later in a MutationObserver callback. If another frontend script assigns a non-element value to that global between initialization and an observed attribute mutation, Neve produces the exact reported html.getAttribute is not a function exception. The ticket stack identifies this observer callback, providing direct alignment between the report and the inspected code.

The reported Unauthorized form result occurred concurrently, but no evidence establishes that the Neve exception causes Fluent Forms' AJAX authorization failure. That relationship remains an inference.

Where this likely occurs

  • User-visible surface: frontend pages with the Header/Footer Builder Logo component active, including pages using the palette switch.
  • header-footer-grid/Core/Components/Logo.phpLogo::register_script() lines 171–176: includes the logo script when the component is active or during a Customizer preview.
  • header-footer-grid/Core/Components/Logo.phpLogo::toggle_script() lines 246–295: declares page-global var html = document.documentElement, then dereferences html.getAttribute() in the observer callback at line 287.
  • inc/core/front_end.phpFront_End::add_scripts() lines 449–474: enqueues neve-script on non-AMP requests and attaches collected Header/Footer Builder code after that handle.
  • header-footer-grid/Core/Script_Register.phpScript_Register::inline_scripts() lines 82–86: concatenates component scripts without introducing a local scope boundary.
  • Git history: commit 2473e2a4fc708e6992434301d3bb0c855586f4c2 introduced the global variable and observer callback; the code is present from tag v3.1.4 through the inspected v4.2.8 revision.

Engineering notes

  • The observer watches all attribute mutations on document.documentElement, rather than only changes to data-neve-theme, so unrelated changes to the root element can reach the delayed dereference.
  • Neve’s own inspected Header/Footer Builder sources contain no second production assignment to the html identifier. A conflicting assignment therefore appears environment- or integration-dependent.
  • The Neve Pro sibling repository contains no production code that emits or modifies neve-script; its inspected frontend MutationObserver usage is confined to WooCommerce gallery behavior and does not participate in this path.
  • No Fluent Forms source is available in the workspace. The authorization response, guest-only condition, and whether the form code changes the relevant global remain outside the confirmed repository evidence.
  • The inspected theme code does not intercept general Fluent Forms submission requests. This limits confirmation to the Neve JavaScript exception, not the reported form failure.

Test coverage status

e2e-tests/specs/customizer/hfg/hfg-logo-component.spec.tsLogo Component palette lines 84–134 exercises successful light/dark logo switching. It does not monitor browser page errors or exercise a page-global collision before an observed attribute change. No focused unit, integration, or e2e coverage for that failure path was found during inspection.

What to verify or explore next

  • May be worth reproducing with current Neve and Fluent Forms versions in a logged-out session while capturing both the browser exception and the form network response.
  • May be worth verifying the source-derived collision case by assigning a non-element value to window.html after page initialization and then changing an attribute on document.documentElement.
  • If reproducible, checking the final rendered scripts and script-optimization output may identify which component assigns the conflicting global value.
  • Comparing guest and authenticated request payloads, status codes, and response bodies may clarify whether Unauthorized is independent of the observer exception.
  • Running npx playwright test e2e-tests/specs/customizer/hfg/hfg-logo-component.spec.ts with page-error collection may confirm the current success path and provide a baseline for the collision case.

Unknowns / follow-up

  • Exact WordPress, Neve, Neve Pro, and Fluent Forms versions were not provided.
  • The active Header/Footer Builder configuration and presence of the palette switch were not provided.
  • The script that changes window.html to a non-element value is unknown.
  • No ticket images were available, and the full console output and failed request details were not provided.

Confidence

Confidence: 84/100

The reported stack points to the same delayed html.getAttribute() dereference found in Neve, and repository inspection confirms that html is a mutable page-global variable that can become a non-element before the observer callback runs. The concurrent Fluent Forms authorization failure remains unproven as a consequence of this exception.


Source: HelpScout #3387322129
Generated by bug-report-triage (ID: bug-report-triage_6a577657d487b7.93897566)

Metadata

Metadata

Assignees

Labels

bug-reportbug-report-triagecustomer reportIndicates the request came from a customer.releasedIndicate that an issue has been resolved and released in a particular version of the product.

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions