[GUI] Firefox: route-change view transition deadlocks ~5s (update callback waits on rAF the pending transition holds)
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- frontend
Research direction
Start with apps/host/src/lib/router.ts and inspect navigateHash() and its document.startViewTransition() update callback. The issue reports a Firefox stall caused by waiting for two animation frames and describes a timeout fallback that was verified locally. Confirm the route transition behavior in Firefox after applying the reported change; the work is done when navigation responds immediately without breaking the crossfade.
Written by the indexing model from the issue text.
Description
Problem: Any route change in the App Host UI (sidebar engine chip, New conversation) makes the page swallow all clicks for ~4-5 s in Firefox, then it recovers by itself. The page is not frozen; a reload is not needed.
Environment: Strata image 0.2.0-beta-nvfp4.3.1 (strata-nvfp4 fork build; apps/host/src/lib/router.ts identical to upstream), Firefox 158.0.1, Fedora Linux, RTX 5090 32 GB, model qwen3.8-flash-next NVFP4, App Host via Caddy on LAN.
Reproduce: Firefox, open the App Host UI, click the engine chip at the sidebar foot (or New conversation). Expected: view crossfades to the target route immediately. Actual: no click anywhere registers for ~4-5 s; CSS animations keep pulsing; the Monitor view's 5 s auto-refresh shows no update until the stall passes; then everything works again. Deterministic on every attempt.
Mechanism: navigateHash() starts a same-document document.startViewTransition() whose update callback flips the hash synchronously, then resolves after two requestAnimationFrame()s:
const transition = document.startViewTransition(
() => new Promise(done => {
window.location.hash = next;
requestAnimationFrame(() => requestAnimationFrame(() => done()));
}),
);
While a pending view transition waits on its update callback, the browser holds the rendering pipeline - and rAF callbacks are rendering-driven. On Firefox this deadlocks until an internal update-pending guard (observed ~4-5 s) forces it through. That single deadlock explains every symptom: the hash already equals the target, so if (window.location.hash === next) return; early-returns on every further navigation click; non-nav clicks land on a paint-held document; timer-driven DOM updates (Monitor refresh) are deferred; and the main thread is idle throughout, so the DevTools console is instant.
Evidence (collected live during stalls, Firefox DevTools):
performance.getEntriesByType('resource')right after recovery: no entry > 300 ms (nothing network-bound).- No long tasks anywhere; console evaluation instant (main thread idle).
- DOM probe (
elementFromPoint, computedpointer-events,[inert]) identical frozen vs. healthy - no input interceptor. - Stall is consistent 4-5 s on every click; setting
document.documentElement.dataset.motion = 'reduced'(which takes the existing non-morph path innavigateHash) removes it immediately. - Chromium never reproduces it, and hidden/background tabs skip view transitions entirely, so headless UI tests structurally cannot catch this.
Note: isWebKitGtk() exists because WebKitGTK crashes on startViewTransition - same API, same engine-quirk category, different failure mode. Firefox's implementation doesn't crash; it starves the callback.
Proposed fix (either suffices):
- Race the frame wait against a deadline, one line:
() => new Promise(done => {
window.location.hash = next;
requestAnimationFrame(() => requestAnimationFrame(done));
setTimeout(done, 250); // safety rail: rAF can be held by the transition itself
})
(Double resolution is a no-op; unaffected engines behave exactly as before. We have shipped this local edit over the built bundle and the stall is gone in Firefox 158.)
- Or gate Firefox the way WebKitGTK is gated, though that drops the crossfade for all Firefox users.
Reproduction status: reproduced locally (two users, every attempt, workaround and fix both verified).
- Dominant language
- C++
- Stars
- 11.6k
- Forks
- 1k
- PR merge metrics
- No merged PRs in 30d
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Niko1221/Strata
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
Maintainers usually reply within 3 days
-
[TUI] `strata launch` worked then, after a tune had been saved for this PC, every later launch failedPossibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
Niko1221/Strata#3613 · 4 comments · 2 reactions ·
Maintainers usually reply within 3 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Niko1221/Strata#3524 · 2 comments ·
Maintainers usually reply within 3 days
-
Difficulty 1/5 Under an hour Newbie friendliness 70/100
Maintainers usually reply within 3 days
-
Difficulty 1/5 Under an hour Newbie friendliness 84/100
Niko1221/Strata#3512 · 1 comment ·
Maintainers usually reply within 3 days
Similar issues
-
Jupyter kernel leaks two file descriptors per cell; after ~100 cells every cell fails with "pipe() failed"Possibly taken A pull request linked to this issue is open or already merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Test discovery aborts on GPU builds without cuStateVec: check_cuStateVec expects a failed result but set_config() now raises RuntimeErrorPossibly taken @dmeliksetian claimed this today. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Qiskit/qiskit-aer#2495 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
sumatrapdfreader/sumatrapdf#6403 ·
-
Module:Polygraphy
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
enhancement GUI maintainer-review
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
aethersdr/AetherSDR#6681 · 1 comment ·
Maintainers usually reply within 1 day