Skip to content

fix(website): retry skill detail fetch and show a clear error (#737) - #738

Merged
luongnv89 merged 2 commits into
mainfrom
fix/737-failed-to-fetch-error-on-skill-detail
Oct 12, 2026
Merged

luongnv89 merged 2 commits into
mainfrom
fix/737-failed-to-fetch-error-on-skill-detail

Conversation

@luongnv89

Copy link
Copy Markdown
Owner

Closes #737

Summary

The skill detail page on the catalog site loads each skill's full details from skills/<slug>.json with a single fetch. When that request failed at the network level, the browser rejected it with a TypeError ("Failed to fetch"). The page then showed that raw text with no retry and no way to recover except leaving the page. SkillDetail now retries transient failures automatically. If the details still cannot be loaded, it shows a plain-language message with a Try again button. The summary and the install command stay usable either way.

Approach

Make the detail fetch in SkillDetail.jsx resilient. The service worker, the catalog build and the generated website/ output are not touched.

  • Retry network errors (TypeError) and HTTP 5xx/408/429 responses up to 2 more times, with a 500 ms then 1500 ms backoff. Never retry a 404 or a JSON parse error.
  • Use an AbortController and clear the retry timer in the effect cleanup, so leaving the page or switching skills stops the old work.
  • On final failure, show a role="alert" message ("The network request failed. Check your connection and try again.") and a Try again button that re-runs the load.

Decision Record

  • Root cause: The per-skill detail JSON for tt-a1i/archify::archify::archify (skills/ee00db11c9ed3afe.json) returns 200 (2.2 KB, same-origin, correct slug) on production, and the deployed service worker is the fix(website): stop stale service-worker caching and refresh OG image #734 network-first asm-catalog-v2. "Failed to fetch" is Chromium's TypeError for a network-level failure and is never an HTTP status (a 404 would read "HTTP 404"). Two paths produce it: a transient network or connection error, or the service worker answering Response.error() when the network fails and nothing is cached (a reporter still on the pre-fix(website): stop stale service-worker caching and refresh OG image #734 worker fails the same way on a cache miss). SkillDetail made exactly one attempt, never retried, and printed the raw message, so any transient failure left the page in that state. The failure did not reproduce on a clean Chrome profile against production.
  • Options considered: Option 1: friendlier error text only; Option 2: bounded retry + clear message + Try again button in SkillDetail; Option 3: Option 2 plus service-worker changes (stale-while-revalidate / precaching detail files)
  • Options rejected: Option 1: still leaves a transient blip as a permanent error until the visitor navigates away; Option 3: no concrete defect was found in the v2 worker, and changing it means editing the tracked website/service-worker.js copy and touching offline caching for no proven gain
  • Selected option: Option 2: bounded retry + clear message + Try again in SkillDetail
  • Residual risk: UI-review note, not fixed: pressing Try again unmounts the focused button while the reload runs, so keyboard focus returns to <body>. If the reporter's failure came from something outside the page (for example, a browser extension blocking the request), a retry will not help. The page now says what failed and stays usable, and the visitor can retry.
  • Effort profile: light: fast path (pre-work Effort S); synthesis skipped, QA capped at 1 cycle
  • Reproduction: npx vitest run website-src/src/__tests__/skill-detail.test.jsx confirmed red before the fix. 4 new tests failed: the fetch rejected with TypeError("Failed to fetch") and nothing retried, and there was no alert or Try again button. → regression tests in website-src/src/__tests__/skill-detail.test.jsx. The live symptom did not reproduce on production with a clean profile.

Analyzed at: main @ 9cb6491 (2026-10-12)

Changes

File Change
website-src/src/components/SkillDetail.jsx Bounded retry with backoff for network/5xx/408/429 failures, abort and timer cleanup, plain-language role="alert" error with a Try again button. The alert uses the site's warn box (warn border and background, --fg text for AA contrast), and the button has a 44px hit area
website-src/src/__tests__/skill-detail.test.jsx 5 regression tests: retry then success, persistent failure + Try again, no retry on 404, 503 retried, no retries after unmount

Test Results

  • Unit tests: 2960 passed (CI=true npm test, 119 files)
  • Integration tests: skipped
  • E2e tests: skipped (pre-push hook runs them)
  • Build: passed (npm run lint:site clean)
  • QA cycles: 1 (light cap). Code review: PASS. Code UI review: 2 accessibility fixes applied in 21ad112 (button hit area, light-theme contrast); the fix was not re-reviewed because of the 1-cycle cap
  • Test integrity: pinned: existing skill-detail.test.jsx cases green before and after, unedited; removed or weakened: none

Manual browser check: headless Chrome over CDP against vite dev with the change, at #/skills/tt-a1i%2Farchify%3A%3Aarchify%3A%3Aarchify:

  • direct load from about:blank and Page.reload: detail JSON fetched (200), no error
  • first detail request failed by injection (Fetch.failRequest ConnectionReset): recovered, no error
  • every attempt failed: clear message plus Try again shown, install command still visible; Try again after the network was restored loaded the details

Acceptance Criteria Verification

Criterion Status Evidence
The detail page for tt-a1i/archify:archify loads its full details without showing "Could not load full details: Failed to fetch" pass Verified red: npx vitest run website-src/src/__tests__/skill-detail.test.jsx → fixed → test "retries a transient network failure and then shows the full details". CDP run on the archify page: no error on normal load, and recovery after an injected network failure
Detail pages for other indexed skills load their full details without this error pass The fix is in the shared SkillDetail component used by every skill page; the regression tests use generic skills
If the details really can't be loaded, the page shows a clear message and keeps the summary and install command usable pass Test "shows a clear message and a retry button when the network stays down" (asserts the alert text, no raw "Failed to fetch", summary and asm install visible, Try again refetches). CDP run with every request failing shows the same
Details still load after the page is reloaded and when the page is opened directly by URL pass CDP run: fresh navigation from about:blank and Page.reload each issued the detail request (200) with no error; failures are never cached (detailCache stores successes only)

Test added 2 commits October 12, 2026 22:37
A network-level failure while loading the per-skill detail JSON
("Failed to fetch") left the detail page stuck on a raw error with no
way to recover short of navigating away. SkillDetail now retries
network errors and 5xx/408/429 responses with a short backoff, aborts
in-flight work on unmount, and on a final failure shows a plain-language
message with a Try again button while the summary and install command
stay usable.
Give the Try again button a 44px hit area (min-h-11) and render the
alert text in --fg inside the warn-bg/warn-border box, keeping --warn
only for the icon and border so light-theme contrast passes WCAG AA.
@luongnv89
luongnv89 merged commit f862014 into main Oct 12, 2026
17 checks passed
@luongnv89
luongnv89 deleted the fix/737-failed-to-fetch-error-on-skill-detail branch October 12, 2026 20:48
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.

Fix "Failed to fetch" error on skill detail page

1 participant