Make the router effect run once and log uncaught exceptions with exc_info - #1198
Merged
Merged
Conversation
…info Grotto hit a production incident (PENG-1257) where a building switch replaced the whole app by a traceback. The router effect had no dependencies, so it queued a widget lookup on every render. A render pass that aborted halfway left that closure with an element that was never reconciled, get_widget raised "was found to be in a previous render" from inside the effect, and the app was gone. reacton 1.10.3 (widgetti/reacton#54, #55) stops the aborted render, but the router should not depend on one effect to stay alive. The root element is always the same VBox at the same slot, so the Navigator widget is created once and reused: the lookup belongs in a run-once effect. get_widget(nav) reaches the widget directly on reacton 1.10.3, so the indirection over the parent container and the comment doubting it are gone. The shell formatted the traceback into the log message. Sentry groups on the message, so every uncaught exception of every app ended up in a single issue titled "Uncaught exception: Traceback (most recent call last):", hiding a TypeError, a reacton AssertionError and several ValueErrors behind one title. Passing the exception via exc_info keeps the message short and lets error trackers group per exception. The traceback string still goes to the frontend over the control socket unchanged.
Contributor
Author
|
Why |
maartenbreddels
force-pushed
the
fix/router-effect-and-uncaught-logging
branch
from
September 3, 2026 12:13
3df1806 to
56aba2a
Compare
maartenbreddels
temporarily deployed
to
fix/router-effect-and-uncaught-logging - solara-stable PR #1198
September 3, 2026 12:13 — with
Render
Destroyed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two changes from a production incident (reacton 1.10.3, widgetti/reacton#54).
Router effect
RoutingProviderre-queuedsolara.get_widget(main)in an effect without dependencies, on every render of the router. When a render pass aborted halfway, reacton before 1.10.3 could do that, the chained closure held an unreconciledmain,get_widgetraised from inside the effect, and the whole app was replaced by the traceback. reacton 1.10.3 fixes the abort; this makes the router not depend on it.solara.use_effect(get_nav_widget, []): the root element of the component is always the sameVBoxat the same slot, reacton updates it in place, so the Navigator widget is the same object for the lifetime of the app. Thenav_widget.current.location = pathline still runs on every render.get_widget(nav)instead ofget_widget(main).children[0]. The old comment said it did not work; it does on reacton 1.10.3:navis a widget element reconciled in the VBox's child context, which the downward search from the router context reaches. The stale comment is gone.test_routing_provider_navigator_widget_stablepushes three paths and one browser-side location change, asserts the widget identity is stable andlocationfollows every push. Rendered withhandle_error=False, so a failing effect would raise.Uncaught exception logging
FakeIPython.showtracebacklogged"Uncaught exception: %s"with the formatted traceback in the message and no exception info. Error trackers group on the message, so every escaped event-handler exception of every app lands in one issue. Nowlogger.error("Uncaught exception", exc_info=value); the pdb branch and the control-socket message with the formatted traceback are unchanged. Test asserts the record carries the exception.🤖 Generated with Claude Code