Describe the bug
On a page with many server callbacks firing at load, a URL-to-component sync set up with two clientside callbacks goes into an infinite loop on 4.5.0rc0. It works on 4.4.1.
readUrl: Input url.search, prevent_initial_call="initial_duplicate". It calls dash_clientside.set_props("tabs", {"value": <tab from ?tab=>}).
tabSearch: Input tabs.value, State url.search, Output url.search (allow_duplicate=True), prevent_initial_call=True. It writes ?tab=<value> back to the URL.
Loading /page?plan=21&tab=history on 4.5.0rc0 gives this trace (store = the tabs.value in window.store):
1397ms store tabs.value undefined -> "scope" (layout default)
1748ms readUrl: set_props("tabs", {value: "history"}) ; store -> "history"
1759ms tabSearch runs, triggered [{"prop_id":"tabs.value","value":"scope"}] <-- stale value
1934ms tabSearch runs, triggered [{"prop_id":"tabs.value","value":"history"}]
... the stale run writes ?plan=21, readUrl sets the tab back to "scope", tabSearch gets "history"... forever
tabSearch runs twice, and the first run gets the layout's stale value even though the store already holds the value set_props wrote. On 4.4.1 it runs once, with "history".
Bisected to the renderer change in observers/prioritizedCallbacks.ts / observers/requestSlot.ts (from #3931, commit ce7530c), which exempts clientside callbacks from the 12-slot HTTP budget. With only !cb.callback.clientside_function && removed from usesRequestSlot in the built dash_renderer.min.js, so clientside callbacks count toward the budget again as in 4.4.1, the same page settles: one request after load, ?tab=history kept, History tab selected. With the stock 4.5.0rc0 renderer the page loops until the browser tab crashes.
The CHANGELOG entry for #3931 doesn't mention the scheduling change.
Repro status
Our reduced app (dmc.Tabs + the two callbacks above, a router callback returning the page, 20 slow server callbacks on load) did NOT reproduce the 4.4.1/4.5 difference, so the exact extra condition is still unknown. The evidence above comes from the full app, where swapping only that renderer line toggles the bug. Happy to test a candidate fix.
Environment: dash 4.5.0rc0 (FastAPI backend), dash-mantine-components 2.8.0, React 18.3.1 (default), Chrome stable (Playwright), Python 3.14.
Workaround: guard the URL writer against its own echo (ignore tabs.value events until the value set_props wrote comes back).
Describe the bug
On a page with many server callbacks firing at load, a URL-to-component sync set up with two clientside callbacks goes into an infinite loop on 4.5.0rc0. It works on 4.4.1.
readUrl: Inputurl.search,prevent_initial_call="initial_duplicate". It callsdash_clientside.set_props("tabs", {"value": <tab from ?tab=>}).tabSearch: Inputtabs.value, Stateurl.search, Outputurl.search(allow_duplicate=True),prevent_initial_call=True. It writes?tab=<value>back to the URL.Loading
/page?plan=21&tab=historyon 4.5.0rc0 gives this trace (store = thetabs.valueinwindow.store):tabSearchruns twice, and the first run gets the layout's stale value even though the store already holds the valueset_propswrote. On 4.4.1 it runs once, with"history".Bisected to the renderer change in
observers/prioritizedCallbacks.ts/observers/requestSlot.ts(from #3931, commit ce7530c), which exempts clientside callbacks from the 12-slot HTTP budget. With only!cb.callback.clientside_function &&removed fromusesRequestSlotin the builtdash_renderer.min.js, so clientside callbacks count toward the budget again as in 4.4.1, the same page settles: one request after load,?tab=historykept, History tab selected. With the stock 4.5.0rc0 renderer the page loops until the browser tab crashes.The CHANGELOG entry for #3931 doesn't mention the scheduling change.
Repro status
Our reduced app (dmc.Tabs + the two callbacks above, a router callback returning the page, 20 slow server callbacks on load) did NOT reproduce the 4.4.1/4.5 difference, so the exact extra condition is still unknown. The evidence above comes from the full app, where swapping only that renderer line toggles the bug. Happy to test a candidate fix.
Environment: dash 4.5.0rc0 (FastAPI backend), dash-mantine-components 2.8.0, React 18.3.1 (default), Chrome stable (Playwright), Python 3.14.
Workaround: guard the URL writer against its own echo (ignore
tabs.valueevents until the valueset_propswrote comes back).