WordPress 7.1 keeps the toolbar available while supported editor screens navigate on the client. A plugin can avoid visible duplicate menu items and still retain event listeners, observers, timers, detached modal nodes, cached responses, or large editor objects after each route change. The symptom may appear only after an editor has moved between posts and the Site Editor for an hour.
Use this for plugins or themes that add toolbar menus, modals, support launchers, environment badges, preview controls, analytics panels, or route-aware actions.
Quick answer
Open a clean browser profile with the exact production plugin set, record a baseline heap snapshot, listener count, DOM node count, timers, observers, and network activity, then run a fixed route loop at least 20 times. Move from the posts list to the Block Editor, Site Editor, front end, and back. Force garbage collection only in a controlled development profile and compare retained objects by constructor and allocation stack. The pass condition is a bounded heap after warm-up, one live handler per owned event, no growing detached subtree, and no repeated request from stale toolbar state.
Test scenarios to run
Run the same controlled fixture across these branches. Write down the expected result before testing so a surprising response is easy to identify.
| Scenario | Fixture | Expected result |
| Warm-up | 3 route loops | Heap reaches a steady range |
| Sustained | 20 route loops | No linear retained growth |
| Modal | Open and close each route | No detached modal tree |
| Failure | One rejected request | No retry or listener multiplication |
Diagnostic table
Use this table to connect the observed behavior to evidence and a verification step.
| Action | Evidence | Verification |
| Define a repeatable route loop | Record the WordPress, browser, theme, plugin, PHP, and Gutenberg versions plus the exact route sequence and wait time between transitions. | Twenty route loops do not create linear heap growth. |
| Capture a warm baseline | Capture heap size, detached nodes, listeners, MutationObservers, intervals, animation frames, open sockets, and owned network requests before and after each route loop. | Detached toolbar and modal nodes return to baseline. |
| Trace retained owners | Tag toolbar roots, modal portals, subscriptions, and callbacks with stable names so retained objects can be traced back to one owner. | Listener, observer, timer, and request counts remain bounded. |
| Clean up every lifecycle resource | Test mouse, keyboard, browser Back and Forward, direct links, modal open and close, role changes, and navigation after a failed request. | Keyboard, Back, Forward, and failed-request paths still work. |
What to check first
- Record the WordPress, browser, theme, plugin, PHP, and Gutenberg versions plus the exact route sequence and wait time between transitions.
- Capture heap size, detached nodes, listeners, MutationObservers, intervals, animation frames, open sockets, and owned network requests before and after each route loop.
- Tag toolbar roots, modal portals, subscriptions, and callbacks with stable names so retained objects can be traced back to one owner.
- Test mouse, keyboard, browser Back and Forward, direct links, modal open and close, role changes, and navigation after a failed request.
- Remove listeners, observers, timers, subscriptions, and portal nodes when their screen context ends, then repeat the identical profile.
Field notes
- Write the expected result before changing anything and keep one repeatable synthetic fixture for the full test window.
- Record exact versions and UTC timestamps because caches, retries, scheduled actions, and deployments can change the evidence between checks.
- Test the public path and the stored server-side result, not only an admin preview, isolated command, or API response.
- Review the result again after the relevant cache, queue, cron, webhook, and observation window has completed.
Useful command or data shape
Adapt paths, IDs, and privacy handling to the site before running commands or storing data on production.
# Chrome DevTools Performance monitor
# Record JS heap, DOM nodes, listeners, and documents.
# Run the same route loop 20 times, wait 5 seconds, then compare snapshots.
# Group retained objects by constructor and allocation stack.
Why this usually happens
- A route callback closes over the previous editor store and is never unsubscribed.
- A MutationObserver watches the document after its toolbar feature is no longer active.
- Modal portals are hidden rather than removed and keep editor data reachable.
- A retry timer survives navigation and starts another request from every prior route.
Decision rule
Ship only when memory reaches a bounded range after warm-up, detached nodes return to baseline, every owned event has one handler, and failed requests do not leave a growing timer or retry chain.
Production verification checklist
- Twenty route loops do not create linear heap growth.
- Detached toolbar and modal nodes return to baseline.
- Listener, observer, timer, and request counts remain bounded.
- Keyboard, Back, Forward, and failed-request paths still work.
Safe fix order
Use a sequence that makes each result easy to prove. Stop when new evidence changes the scope or owner of the problem.
- Define a repeatable route loop
- Capture a warm baseline
- Trace retained owners
- Clean up every lifecycle resource
- Repeat and set an alert threshold
Mistakes to avoid
- Changing production before recording exact versions, UTC timestamps, a stable fixture, the expected result, and a tested rollback point.
- Treating one successful screen as proof while logs, stored records, background jobs, caches, emails, APIs, and downstream systems remain unchecked.
- Testing only as an administrator instead of using the role, device, locale, cache state, request path, and failure branch that users actually reach.
- Leaving debug output, temporary exclusions, helper accounts, duplicate hooks, broad permissions, or relaxed firewall rules active after verification.
Questions teams ask during testing
Can I test this directly in production?
Start with read-only evidence. Use staging for code, package, security, checkout, form, privacy, or cache changes. If a production canary is necessary, make it identifiable, reversible, monitored, and incapable of exposing personal data or charging a customer.
How do I avoid a false positive?
Repeat the same fixture with the same versions, URL, role, locale, cache state, and downstream integration. Compare the public result, stored result, and logs instead of relying on one browser view.
What evidence should I retain?
Keep UTC time, exact versions, request or record ID, expected result, actual result, relevant log lines, change made, rollback point, owner, and final verification. Redact credentials, tokens, and personal data.
When is the work complete?
Close it when the primary path passes, failure branches are understood, stored and downstream records reconcile, temporary changes are removed, monitoring is active, and the owner has the evidence packet.
What to tell the client or owner
Give the owner a concise packet with the affected workflow, exact versions, UTC test time, synthetic fixture ID, expected result, actual result, key logs, change made, rollback point, final result, unresolved risks, owner, and next review date. Remove credentials and personal data before sharing it.
When HandL WP should help
Bring in help when this affects leads, checkout, search visibility, security, paid media reporting, or a client production site. HandL WP can trace the issue through WordPress, hosting, cache, tracking, and Search Console, then verify the workflow after the technical fix.
If this is active on a production site, have HandL WP profile a WordPress 7.1 editor integration.
Related HandL WP guides
Use these related guides when the same issue touches tracking, security, checkout, or crawler visibility.
Alert on retained store subscriptions
Turn the long-session profile into a release guard with the WordPress 7.1 toolbar retained store subscription alert. It counts active subscriptions, callbacks, stale-generation requests, detached nodes, and bounded heap across the same route loop.
Helpful references