Failed evidence fetch renders as "No evidence yet." #78
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Severity: HIGH
The bug
frontend/src/pages/ReviewWorkspacePage.tsx:87-118destructures onlydatafromuseQuery, then:Loading and error states are collapsed into the empty state. If
/evidencereturns a 500, or thesession has expired, the panel tells the reviewer there is no evidence — and they decide on
that basis.
The same pattern appears in
CommentsTab(:295-310) andHistoryTab(:337-344).Why it matters
"Evidence-first" is the product's stated first principle, and
docs/circa-ui-spec.md§9.3/§9.5explicitly forbid collapsing these states. A reviewer who trusts a false "No evidence yet" will
approve or dispute on wrong grounds — and the resulting decision looks completely legitimate in
the history.
This is the most dangerous five-line bug in the frontend.
Fix
isLoadinganderrorin all three sections and render distinct states:"Loading evidence…" and "Couldn't load evidence — Retry".
QueryCache.onErrorhook in the client) that redirects to login.Today an expired session mid-review just makes every panel quietly fail.
Done when
References
frontend/src/pages/ReviewWorkspacePage.tsx:87-118,295-310,337-344docs/circa-ui-spec.md§9.3, §9.5Done in
88044bc. All four "done when" items covered.Your description of this as "the most dangerous five-line bug in the frontend" is right, and I'd add one thing: it was in four places, not three —
NotesHistory(added with #66) had inherited the same shape. That's the argument for fixing it as a sharedAsyncPanelrather than four corrected conditionals. The bug existed four times because the shape was duplicated four times, and a fifth panel written next month would have inherited it too.Loading / error / empty are now genuinely distinct, error carries a Retry (the failure is usually transient and a reviewer shouldn't have to reload the workspace to find out), and error uses
role="alert"so it is announced rather than merely coloured.The 401 handler is a
QueryCache+MutationCacheonError, guarded against redirect loops. I also turned off retries for 4xx generally: a 401 is a settled answer, and retrying it delays the redirect while spending the auth rate limit from #68 on a session that is already gone. Worth noting this stopped being an exotic case when #61 shortened sessions to a 12-hour idle window — an expired session mid-review is now routine.Tests: this needed frontend tooling, which didn't exist, so vitest + Testing Library + jsdom came with it and are wired into CI. That's the tooling half of #11 — I've left #11 open for the review-workspace coverage it also asks for. 10 tests, including the exact failure mode:
items === undefinedwith no error must not render the empty state.One related fix rides along in the dashboard (#83): a dash now means "could not find out" and zero means zero, which is the same principle applied to a different panel.