Summary
Header or footer component selective refresh can terminate with Call to a member function get_id() on null.
Expected behavior: refreshing a Header Footer Grid component in the Customizer renders that component's markup.
Actual behavior: the refresh request can resolve no component and the wrapper dereferences it, producing a fatal error.
Impact: affected Customizer refresh requests fail instead of updating the preview.
Customer context
- Product / area: Neve Header Footer Grid, Customizer selective refresh
- Version: 4.2.10
- Environment: WordPress 7.0.2; observed with PHP 8.2.32, 8.2.33, and 8.5.3-nmm1
- Integration / third party: None identified
- Reported error / symptom:
Call to a member function get_id() on null during a frontend selective-refresh request
- Impact: 3 occurrences across 3 production sites in the telemetry query window (2026-08-01 to 2026-08-04).
Reproduction notes
- In the WordPress Customizer, use Header Footer Grid components from more than one builder.
- Trigger a selective refresh for a component after another builder component has been rendered in the same request lifecycle.
- Observed production result: the partial-render request reaches the wrapper with no resolved component and fatals at
get_id().
Production telemetry confirms the failing request path. The exact setting-change sequence and component IDs are unavailable.
Diagnosis
Conclusion
Production telemetry identifies the fatal at component-wrapper.php:13 during WordPress Customizer selective refresh. Repository inspection confirms that the wrapper dereferences current_component() without a null check, while the selective-refresh callback can leave a stale static builder component ID preferred over its own component ID. If that stale ID is absent from the callback's selected builder, get_component() returns null, matching the reported fatal.
Where this likely occurs
header-footer-grid/templates/component-wrapper.php — approx. lines 13-37, component wrapper template: calls current_component()->get_id() and several other instance methods without confirming that a component was resolved.
header-footer-grid/Core/Components/Abstract_Component.php — lines 604-612, Abstract_Component::customize_register(): registers each component's selective-refresh render_callback.
header-footer-grid/Core/Components/Abstract_Component.php — lines 622-630, Abstract_Component::render(): sets Abstract_Component::$current_component and Abstract_Builder::$current_builder, then loads the wrapper.
header-footer-grid/Core/Builder/Abstract_Builder.php — lines 1708-1714, Abstract_Builder::get_component(): when no explicit ID is supplied, it prefers Abstract_Builder::$current_component; an absent key resolves to null despite the method's nullable return contract.
header-footer-grid/Core/Builder/Abstract_Builder.php — lines 1456-1458 in Abstract_Builder::new_render_components() and lines 1660-1664 in Abstract_Builder::render_components(): normal rendering persists the static builder component ID that can be reused by a later lookup.
- The unsafe wrapper is present at release tag
v4.2.10, which matches the inspected HEAD release commit ba9965943.
Engineering notes
The reported stack reaches Abstract_Component::render() through WP_Customize_Partial::render, so the affected surface is Customizer selective refresh rather than ordinary full-page component rendering. HFG\current_component() in header-footer-grid/functions-template.php lines 56-65 delegates to the selected builder's get_component() without supplying the callback component ID. The observed cross-builder stale-state sequence is a code-path inference; telemetry confirms the resulting null dereference but does not identify the specific component pair. Neve Pro adds template locations but no component-wrapper.php override or alternate core Abstract_Component::render() path was found.
Test coverage status
No relevant PHP coverage was found during inspection for HFG\current_component(), Abstract_Builder::get_component(), the wrapper template, or a cross-builder selective-refresh sequence. Existing HFG Playwright coverage, including e2e-tests/specs/customizer/hfg/hfg-logo-component.spec.ts, hfg-search-component.spec.ts, and hfg-copyright-component.spec.ts, covers component settings or rendered output but not selective-refresh callback state resolution.
What to verify or explore next
- May be worth reproducing in the Customizer by rendering one builder component before selectively refreshing a component registered to another builder.
- If reproducible, checking the selective-refresh response and PHP warnings around an absent builder component key would establish the exact stale ID sequence.
- Running the HFG Customizer Playwright suite after adding coverage for a cross-builder partial refresh would validate the affected request path.
Unknowns / follow-up
- Telemetry does not include the specific component IDs, Customizer setting change, or persisted builder layout that led to the null lookup.
- The inspected repository does not include WordPress core, so selective-refresh lifecycle details outside the captured stack are not locally verified.
Confidence
Confidence: 95/100
Production telemetry captures the fatal on three sites running Neve 4.2.10, and the inspected selective-refresh path can resolve a stale component ID against the selected builder and return null immediately before the reported dereference.
Crash telemetry
|
|
| Occurrences |
3 |
| Distinct sites |
3 |
| First seen |
2026-08-01 19:40 UTC |
| Last seen |
2026-08-04 20:02 UTC |
| Crash location |
product:header-footer-grid/templates/component-wrapper.php:13 |
| Request context |
frontend |
| Inside Themeisle SDK |
no |
| Product versions |
4.2.10 |
| WP versions |
7.0.2 |
| PHP versions |
8.2.32, 8.2.33, 8.5.3-nmm1 |
| SDK versions |
3.3.59 |
Source: automated crash report — neve, fingerprint ea7bc15abbadc84d541c5d743698a4e1
Generated by bug-report-triage (ID: bug-report-triage_6a72d1811f8d79.15346783)
Summary
Header or footer component selective refresh can terminate with
Call to a member function get_id() on null.Expected behavior: refreshing a Header Footer Grid component in the Customizer renders that component's markup.
Actual behavior: the refresh request can resolve no component and the wrapper dereferences it, producing a fatal error.
Impact: affected Customizer refresh requests fail instead of updating the preview.
Customer context
Call to a member function get_id() on nullduring a frontend selective-refresh requestReproduction notes
get_id().Production telemetry confirms the failing request path. The exact setting-change sequence and component IDs are unavailable.
Diagnosis
Conclusion
Production telemetry identifies the fatal at
component-wrapper.php:13during WordPress Customizer selective refresh. Repository inspection confirms that the wrapper dereferencescurrent_component()without a null check, while the selective-refresh callback can leave a stale static builder component ID preferred over its own component ID. If that stale ID is absent from the callback's selected builder,get_component()returnsnull, matching the reported fatal.Where this likely occurs
header-footer-grid/templates/component-wrapper.php— approx. lines 13-37, component wrapper template: callscurrent_component()->get_id()and several other instance methods without confirming that a component was resolved.header-footer-grid/Core/Components/Abstract_Component.php— lines 604-612,Abstract_Component::customize_register(): registers each component's selective-refreshrender_callback.header-footer-grid/Core/Components/Abstract_Component.php— lines 622-630,Abstract_Component::render(): setsAbstract_Component::$current_componentandAbstract_Builder::$current_builder, then loads the wrapper.header-footer-grid/Core/Builder/Abstract_Builder.php— lines 1708-1714,Abstract_Builder::get_component(): when no explicit ID is supplied, it prefersAbstract_Builder::$current_component; an absent key resolves tonulldespite the method's nullable return contract.header-footer-grid/Core/Builder/Abstract_Builder.php— lines 1456-1458 inAbstract_Builder::new_render_components()and lines 1660-1664 inAbstract_Builder::render_components(): normal rendering persists the static builder component ID that can be reused by a later lookup.v4.2.10, which matches the inspectedHEADrelease commitba9965943.Engineering notes
The reported stack reaches
Abstract_Component::render()throughWP_Customize_Partial::render, so the affected surface is Customizer selective refresh rather than ordinary full-page component rendering.HFG\current_component()inheader-footer-grid/functions-template.phplines 56-65 delegates to the selected builder'sget_component()without supplying the callback component ID. The observed cross-builder stale-state sequence is a code-path inference; telemetry confirms the resulting null dereference but does not identify the specific component pair. Neve Pro adds template locations but nocomponent-wrapper.phpoverride or alternate coreAbstract_Component::render()path was found.Test coverage status
No relevant PHP coverage was found during inspection for
HFG\current_component(),Abstract_Builder::get_component(), the wrapper template, or a cross-builder selective-refresh sequence. Existing HFG Playwright coverage, includinge2e-tests/specs/customizer/hfg/hfg-logo-component.spec.ts,hfg-search-component.spec.ts, andhfg-copyright-component.spec.ts, covers component settings or rendered output but not selective-refresh callback state resolution.What to verify or explore next
Unknowns / follow-up
Confidence
Confidence: 95/100
Production telemetry captures the fatal on three sites running Neve 4.2.10, and the inspected selective-refresh path can resolve a stale component ID against the selected builder and return
nullimmediately before the reported dereference.Crash telemetry
product:header-footer-grid/templates/component-wrapper.php:13Source: automated crash report — neve, fingerprint
ea7bc15abbadc84d541c5d743698a4e1Generated by bug-report-triage (ID: bug-report-triage_6a72d1811f8d79.15346783)