Skip to content

Fix Dashboard crash when navigating between routes with a Dashboard component#130

Merged
roncodes merged 2 commits into
mainfrom
fix/dashboard-reset-tracking-frame-violation
May 20, 2026
Merged

Fix Dashboard crash when navigating between routes with a Dashboard component#130
roncodes merged 2 commits into
mainfrom
fix/dashboard-reset-tracking-frame-violation

Conversation

@roncodes
Copy link
Copy Markdown
Member

Summary

Hotfix for a regression introduced in #129 (v0.3.30). Navigating from one route that mounts <Dashboard> to another route that also mounts <Dashboard> (e.g. host home → a fleetops engine route, or vice versa) crashes the app with:

Assertion Failed: You attempted to update <RelatedCollection:dashboard-widget>.length, but it had already been used previously in the same computation.

Root cause

DashboardComponent's constructor runs during a render. The constructor synchronously calls dashboard.reset(), which since #129 synchronously calls store.unloadAll('dashboard-widget') + store.unloadAll('dashboard'). The previous Dashboard render had already consumed <RelatedCollection:dashboard-widget>.length in the same tracking frame, so the unload's tag mutation violates Ember's "no mutate after consume in the same computation" rule and tears down rendering.

Fix

Schedule both the store unloads (inside reset()) and the loadDashboards.perform() call (in the component constructor) onto the next runloop tick via next(). They queue in registration order, so the unloads run first, then loadDashboards re-queries against a clean store — and crucially both happen after the in-flight render finishes, keeping the tag mutation outside the consumed tracking frame.

The prior code had this pattern; #129 removed the next() wrappers in a misguided "simplification." Restoring them with a comment explaining why they're load-bearing.

Test plan

  • Mount a <Dashboard> at the host home route, navigate to a fleetops engine route that also mounts a <Dashboard> — no assertion fires, both render cleanly.
  • Reverse direction (engine → host) — same.
  • Reload the page on either route — <Dashboard> renders, no console errors.
  • Existing tests still pass (ember test).
  • All three lints pass (npm run lint).

🤖 Generated with Claude Code

roncodes and others added 2 commits May 20, 2026 18:01
Crashes the app with "Assertion Failed: You attempted to update
<RelatedCollection:dashboard-widget>.length, but it had already been used
previously in the same computation" whenever a user navigates between two
routes that both mount a <Dashboard> component (e.g. host dashboard → a
fleetops engine route with its own dashboard, or vice versa).

Root cause: DashboardComponent's constructor runs DURING a render. The
constructor synchronously calls dashboard.reset(), which since 098141a
synchronously calls store.unloadAll('dashboard-widget') +
store.unloadAll('dashboard'). The previous Dashboard render had already
consumed `<RelatedCollection:dashboard-widget>.length` in that same
tracking frame, so the unload's tag mutation violates Ember's "no mutate
after consume in the same computation" rule and tears down rendering.

Fix: schedule both the store unloads (inside reset()) and the
loadDashboards.perform() call (in the component constructor) onto the
next runloop tick via next(). They queue in registration order, so the
unloads run first, then loadDashboards re-queries against a clean store
— and crucially both happen AFTER the in-flight render finishes,
keeping the tag mutation outside the consumed tracking frame.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@roncodes roncodes merged commit 9ca6917 into main May 20, 2026
3 checks passed
@roncodes roncodes deleted the fix/dashboard-reset-tracking-frame-violation branch May 20, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant