Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions apps/web/src/routes/__root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
type ErrorComponentProps,
useLocation,
useNavigate,
useRouter,
} from "@tanstack/react-router";
import { useEffect, useEffectEvent, useRef, useState } from "react";

Expand Down Expand Up @@ -188,6 +189,36 @@ function RootRouteErrorView({ error, reset }: ErrorComponentProps) {
const message = errorMessage(error);
const details = errorDetails(error);

// The root error boundary is shown when beforeLoad's startup probe
// (resolveInitialServerAuthGateState -> fetchSessionState) throws. That failure
// is frequently transient (backend still starting, a flaky session call), but
// the boundary persists until a manual reload. Auto-retry when the window
// regains focus/visibility or the network returns, so a recovered backend
// un-sticks the app instead of stranding the user here. reset() only resets the
// boundary; router.invalidate() re-runs beforeLoad. See #3513.
const router = useRouter();
const retryingRef = useRef(false);
useEffect(() => {
const retry = () => {
if (retryingRef.current) return;
retryingRef.current = true;
void router.invalidate().finally(() => {
retryingRef.current = false;
});
};
const retryIfVisible = () => {
if (document.visibilityState === "visible") retry();
};
document.addEventListener("visibilitychange", retryIfVisible);
window.addEventListener("focus", retry);
window.addEventListener("online", retry);
return () => {
document.removeEventListener("visibilitychange", retryIfVisible);
window.removeEventListener("focus", retry);
window.removeEventListener("online", retry);
};
}, [router]);

return (
<div className="relative flex min-h-screen items-center justify-center overflow-hidden bg-background px-4 py-10 text-foreground sm:px-6">
<div className="pointer-events-none absolute inset-0 opacity-80">
Expand Down
Loading