fix(frontend): analysis progress freeze and deep-link 404 crash#198
Merged
parthrohit22 merged 2 commits intoJul 26, 2026
Merged
Conversation
The poll loop rebuilt its interval on every progress tick (repository object identity changed each response) and kept scheduling another request even after a completed/failed/cancelled response, leaving the "Analysing Repository" page stuck until a manual reload. The loop now stops itself on a terminal status and the effect only restarts on an actual status/error change, not every progress percentage.
Direct navigation to /dashboard or /analysis/{id}/architecture hit
react-router's default error boundary ("Unexpected Application Error!
404 Not Found") because no route matched them and there was no
catch-all. /dashboard now aliases the Dashboard surface at /, the
architecture deep link selects that repository and hands off to
/architecture, and any other unmatched path renders a NotFound page
instead of crashing. The auth guard still gates all of this.
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.
Summary
Two related P1 frontend bugs, fixed in one branch per issue owner's request: the "Analysing Repository" page could get stuck displaying a non-terminal state after the backend job actually finished, and direct navigation to certain in-app URLs crashed with react-router's raw "Unexpected Application Error! 404 Not Found" screen instead of a real page. Both are frontend-only; no backend files were touched.
Linked issue
Closes #175. Closes #179.
What changed
Frontend — #175 (
useAnalysisPipeline.ts)fetchAnalysisStatusrequest even after receiving acompleted/failed/cancelledresponse, relying entirely on the surrounding effect tearing itself down on the next render to actually stop. It now returns immediately after handling a terminal response, so the loop's own control flow — not incidental render timing — is what stops it.repositoryobject, whose identity changes on every single progress tick (not just on a real status change), tearing down and rebuilding the interval on every tick (called out in-code as a "known limitation"). The effect now depends on the derivedrepositoryStatus/repositoryErrorMessageprimitives instead, so it only restarts on an actual status or error-message change.Frontend — #179 (
router.tsx+ two new pages)path: '*'route rendering a newNotFoundPageinstead of falling through to react-router's default error boundary. It still sits behindRequireAuth/MainLayout, so an unauthenticated visitor to a bogus path is redirected to/loginfirst, same as any other route./dashboardas an alias (<Navigate to="/" replace />) for the Dashboard surface, whose registered path is/./analysis/:id/architecture, backed by a newAnalysisArchitectureRedirectcomponent that selects the requested repository (setActiveRepositoryId) and hands off to the existing top-level/architectureroute, since Architecture (like Review/Dependencies/Insights) reads the globally-selected repository rather than being mounted per-repository.Acceptance criteria completed
#175
completed/failed/cancelled, the UI reflects the terminal state with no reload and routes to the analysed repository (existingcompletedRepositoryPath→<Navigate>wiring, now backed by a poll loop that reliably reaches and stays in that state).#179
/dashboard,/analysis/{id}/architecture) are directly reachable without a hard-refresh 404.Testing performed
New/changed test coverage:
useAnalysisPipeline.test.ts: added a case asserting the poll loop stops issuing requests once it observes a terminal status, instead of scheduling another one.AnalysisPipelinePage.integration.test.tsx(new): exercises the real hook wired to the real store (the siblingAnalysisPipelinePage.test.tsxmocks the hook entirely, which is exactly the gap between "hook transitions correctly in isolation" and "page actually sees it"). Covers: poll → completed navigates to the repo detail route with no reload; a real job failure renders "Analysis Failed"; a transient network error shows the retrying banner and then recovers to completed.router.test.tsx(new): renders the realcreateAppRouter()output (not a mocked route table) for/dashboard,/analysis/{id}/architecture, and an unknown path, asserting each renders its real page (Dashboard / Architecture / NotFound) instead of the crash screen, and that the architecture deep link selects the requested repository.I could not exercise this in an actual browser in this environment (no backend running, no browser/screenshot tooling available) — verification is via the vitest suite above, which renders the real
react-router-domroute table and the real hook/store wiring in jsdom rather than mocking route matching or the poll loop away.Screenshots
Not applicable for the #175 fix (no markup changes, only control-flow/state-management changes to an existing page).
For #179,
NotFoundPageis a new visible surface, but I have no browser/screenshot tooling in this environment to capture it. It reuses the existingPageHeader+EmptyStatecomponents already used byDeferredSurfacePage(title "Page not found", a compass icon, a short description, and a "Back to Dashboard" action) so it matches the app's existing empty-state styling rather than introducing new visual design. Reviewer can verify withnpm run devand a hard refresh on/dashboard,/analysis/<a-repo-id>/architecture, or any bogus path.Security and data considerations
None. The catch-all and new aliases add no new data access — they only add routes/redirects, and all of them remain nested under the existing
RequireAuthguard, so an unauthenticated request to any of them still redirects to/loginfirst. No secrets, auth logic, or owner-scoping were touched.Dependencies and blocked work
None.
Scope changes or remaining work
None for the verified repro steps in both issues. Note: Review/Dependencies/Insights follow the same "reads the globally-selected repository" pattern as Architecture but weren't reported as 404ing and aren't part of either issue's acceptance criteria, so I left them as top-level-only routes rather than adding matching
/analysis/:id/<surface>deep links for all of them.Contributor checklist
devupstream/devupstream/devCloses) is used only because the issue is fully resolved