Skip to content

Make the router effect run once and log uncaught exceptions with exc_info - #1198

Merged
maartenbreddels merged 1 commit into
masterfrom
fix/router-effect-and-uncaught-logging
Sep 3, 2026
Merged

Make the router effect run once and log uncaught exceptions with exc_info#1198
maartenbreddels merged 1 commit into
masterfrom
fix/router-effect-and-uncaught-logging

Conversation

@maartenbreddels

Copy link
Copy Markdown
Contributor

Two changes from a production incident (reacton 1.10.3, widgetti/reacton#54).

Router effect

RoutingProvider re-queued solara.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 unreconciled main, get_widget raised 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 same VBox at the same slot, reacton updates it in place, so the Navigator widget is the same object for the lifetime of the app. The nav_widget.current.location = path line still runs on every render.
  • get_widget(nav) instead of get_widget(main).children[0]. The old comment said it did not work; it does on reacton 1.10.3: nav is 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: test_routing_provider_navigator_widget_stable pushes three paths and one browser-side location change, asserts the widget identity is stable and location follows every push. Rendered with handle_error=False, so a failing effect would raise.

Uncaught exception logging

FakeIPython.showtraceback logged "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. Now logger.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

…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.
@maartenbreddels

Copy link
Copy Markdown
Contributor Author

Why get_widget(nav) works now, and why it did not when the comment was written in 2023 (#81): reacton's get_widget only searched the current component context then, and nav is reconciled inside the VBox component's child context, hence the detour via get_widget(main).children[0]. reacton dfdca66, "get_widget did not always work for function components", released in v1.7.2, made it search child contexts. solara requires reacton>=1.9, so the detour is no longer needed on any supported reacton. The code comment now records this.

@maartenbreddels
maartenbreddels force-pushed the fix/router-effect-and-uncaught-logging branch from 3df1806 to 56aba2a Compare September 3, 2026 12:13
@maartenbreddels
maartenbreddels temporarily deployed to fix/router-effect-and-uncaught-logging - solara-stable PR #1198 September 3, 2026 12:13 — with Render Destroyed
@maartenbreddels
maartenbreddels merged commit e9ba299 into master Sep 3, 2026
59 of 68 checks passed
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