Skip to content

fix(ui): surface shared ErrorState for GapsPanel fetch failures (#3961)#4907

Closed
shin-core wants to merge 1 commit into
JSONbored:mainfrom
shin-core:fix/gaps-panel-error-state-v3
Closed

fix(ui): surface shared ErrorState for GapsPanel fetch failures (#3961)#4907
shin-core wants to merge 1 commit into
JSONbored:mainfrom
shin-core:fix/gaps-panel-error-state-v3

Conversation

@shin-core

Copy link
Copy Markdown
Contributor

Summary

GapsPanel (apps/ui/src/routes/subnets.$netuid.tsx) was the only tab-panel on the subnet detail page handling loading/error manually via plain useQuery; on a genuine fetch error it rendered the same flat EmptyState used for the "no outstanding gaps" success case (just different copy, "Gaps unavailable") — no red border, no retry. Every sibling tab wraps its fetch in QueryErrorBoundary + Suspense and gets the shared red-bordered ErrorState (with Retry) on failure.

This migrates GapsPanel to that same pattern: the wrapper renders SectionAnchor + QueryErrorBoundary + Suspense, and an inner GapsList uses useSuspenseQuery. A genuine error now surfaces the shared ErrorState automatically; the "no outstanding gaps" success EmptyState is unchanged.

Change

  • One file: subnets.$netuid.tsx (GapsPanel split into GapsPanel wrapper + GapsList).
  • Removes the manual isLoading skeleton branch (now the Suspense fallback) and the manual errorEmptyState branch (now the boundary's shared ErrorState).
  • No change to subnetGapsQuery or the "no outstanding gaps" definition (issue non-goals); compact overview usage preserved via the compact title prop.

Verification (behavioral)

Aborting /api/v1/subnets/1/gaps on /subnets/1?tab=gaps: the panel now renders the shared ErrorState ("Couldn't load…" + Retry) after React Query's retry backoff, and the old flat "Gaps unavailable" EmptyState no longer appears. The success case is unchanged.

Screenshots

Gaps fetch blocked on /subnets/1?tab=gaps. Before: flat borderless "Gaps unavailable" empty-state (no retry). After: the shared red-bordered ErrorState with a Retry action, matching the sibling tabs.

Viewport · Theme Before After
Desktop · Light
before

after
Desktop · Dark
before

after
Tablet · Light
before

after
Tablet · Dark
before

after
Mobile · Light
before

after
Mobile · Dark
before

after

Validation

npm run lint --workspace=apps/ui        # 0 errors
npm run typecheck --workspace=apps/ui   # clean
npm test --workspace=apps/ui            # 665 passed
npm run test:e2e --workspace=apps/ui    # 24 passed (incl. /subnets/1)

Closes #3961

@shin-core shin-core requested a review from JSONbored as a code owner July 11, 2026 15:42
@superagent-security

Copy link
Copy Markdown

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.87%. Comparing base (b15be61) to head (5c91613).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #4907   +/-   ##
=======================================
  Coverage   97.87%   97.87%           
=======================================
  Files         162      162           
  Lines       19986    19986           
  Branches     7508     7508           
=======================================
  Hits        19562    19562           
  Misses         59       59           
  Partials      365      365           
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gittensory-orb gittensory-orb Bot added the gittensor:bug Gittensor-scored bug fix or unsolicited PR — scores a 0.05x multiplier. label Jul 11, 2026
@gittensory-orb

gittensory-orb Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Warning

🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨🟨

⏸️ Gittensory review result - manual review recommended

Review updated: 2026-07-11 15:49:13 UTC

1 file · 2 AI reviewers · no blockers · readiness 100/100 · CI green · clean

⏸️ Suggested Action - Manual Review

  • Touches a guarded path — held for manual review: This PR changes guardrail-protected path(s): apps/ui/src/routes/subnets.$netuid.tsx (matched apps/ui/src/routes/**).

Review summary
GapsPanel is refactored to match the sibling-tab pattern: a wrapper renders SectionAnchor + QueryErrorBoundary + Suspense, and a new GapsList inner component uses useSuspenseQuery instead of the previous manual isLoading/error handling. This correctly routes genuine fetch errors to the shared red-bordered ErrorState (with Retry) instead of the flat 'Gaps unavailable' EmptyState, while leaving the 'no outstanding gaps' success EmptyState and subnetGapsQuery untouched. The split is mechanical and consistent with how other tab panels on this page are structured.

Nits — 7 non-blocking
  • No test coverage was added for the new GapsList/useSuspenseQuery split, unlike the ratio-0.00 test evidence noted for this file — consider a test asserting the error path now renders ErrorState.
  • The wrapper's SectionAnchor id/title/subtitle/info props are now only set in GapsPanel, so verify the Suspense fallback Skeleton and QueryErrorBoundary's ErrorState render inside the same SectionAnchor context as before (visually consistent placement).
  • Confirm GapsList's useSuspenseQuery call reuses the same subnetGapsQuery(netuid) key/config as the old useQuery to avoid duplicate cache entries.
  • Since this is the last of the tab panels migrated to the shared error-boundary pattern per the PR description, consider a brief comment or follow-up noting all panels are now consistent, to prevent future regressions to ad-hoc error handling.
  • apps/ui/src/routes/subnets.$netuid.tsx:GapsPanel now relies on the shared error boundary behavior but adds no focused test or story coverage for the fetch-error rendering path, so this regression could reappear without a targeted assertion.
  • Code changes lack test evidence — Add focused regression tests or explain why existing coverage is sufficient.
  • Touches a guarded path — held for manual review — A maintainer must review and merge this change.
Signal Result Evidence
Code review ✅ No blockers 2 reviewers, synthesized
Linked issue ✅ Linked #3961
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 43 registered-repo PR(s), 22 merged, 0 issue(s).
Contributor context ✅ Confirmed Gittensor contributor shin-core; Gittensor profile; 43 PR(s), 0 issue(s).
Gate result ⚠️ Not blocking Advisory; not blocking this PR.
Linked issue satisfaction

Addressed
The diff migrates GapsPanel to the QueryErrorBoundary + Suspense pattern (splitting it into a GapsPanel wrapper and a GapsList using useSuspenseQuery), removing the manual isLoading/error branches so a fetch failure now surfaces the shared ErrorState instead of the EmptyState, while the 'no outstanding gaps' EmptyState is preserved unchanged.

Review context
  • Author: shin-core
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 43 PR(s), 0 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
[BETA] Chat with Gittensory

Ask Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @gittensory ask <question> answers contribution-quality Q&A with source citations and freshness.
  • @gittensory chat <question> answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @gittensory mention with a real question is routed to the closest matching read-only command automatically -- no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands

Visual preview
Route Viewport Before (production) After (this PR's preview) Diff
/ desktop before / after /
/ mobile before / (mobile) after / (mobile)

Click any thumbnail to open the full-size screenshot. Before = production · After = this PR's preview deploy.

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@gittensory-orb gittensory-orb Bot added the manual-review Gittensor contributor context label Jul 11, 2026

@JSONbored JSONbored left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently blocked by #4867 (as mentioned in Discord overnight), please hold off on further UI / frontend PRs until I get the UI refactor/package completed.

The UI issue direction will be shifting and new tools (like Claude Design) will be able to be easily used once I finish, which will allow for far better design opportunities and overall better submissions.

Also, your error states appear left aligned when they should be centered, pretty sure we already have that pattern established elsewhere in the repo, so please confirm + follow that pre-existing pattern.

Closing.

@JSONbored JSONbored closed this Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:bug Gittensor-scored bug fix or unsolicited PR — scores a 0.05x multiplier. manual-review Gittensor contributor context

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GapsPanel on the subnet detail page shows a genuine fetch error using the same look as "no gaps found" (success)

2 participants