Repository navigation
fix(website): retry skill detail fetch and show a clear error (#737) - #738
Merged
Merged
Conversation
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.
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.
Closes #737
Summary
The skill detail page on the catalog site loads each skill's full details from
skills/<slug>.jsonwith a singlefetch. When that request failed at the network level, the browser rejected it with aTypeError("Failed to fetch"). The page then showed that raw text with no retry and no way to recover except leaving the page.SkillDetailnow 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.jsxresilient. The service worker, the catalog build and the generatedwebsite/output are not touched.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.AbortControllerand clear the retry timer in the effect cleanup, so leaving the page or switching skills stops the old work.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
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-firstasm-catalog-v2. "Failed to fetch" is Chromium'sTypeErrorfor 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 answeringResponse.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).SkillDetailmade 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.SkillDetail; Option 3: Option 2 plus service-worker changes (stale-while-revalidate / precaching detail files)website/service-worker.jscopy and touching offline caching for no proven gainSkillDetail<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.npx vitest run website-src/src/__tests__/skill-detail.test.jsxconfirmed red before the fix. 4 new tests failed: the fetch rejected withTypeError("Failed to fetch")and nothing retried, and there was no alert or Try again button. → regression tests inwebsite-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
website-src/src/components/SkillDetail.jsxrole="alert"error with a Try again button. The alert uses the site's warn box (warn border and background,--fgtext for AA contrast), and the button has a 44px hit areawebsite-src/src/__tests__/skill-detail.test.jsxTest Results
CI=true npm test, 119 files)npm run lint:siteclean)21ad112(button hit area, light-theme contrast); the fix was not re-reviewed because of the 1-cycle capskill-detail.test.jsxcases green before and after, unedited; removed or weakened: noneManual browser check: headless Chrome over CDP against
vitedev with the change, at#/skills/tt-a1i%2Farchify%3A%3Aarchify%3A%3Aarchify:about:blankandPage.reload: detail JSON fetched (200), no errorFetch.failRequestConnectionReset): recovered, no errorAcceptance Criteria Verification
tt-a1i/archify:archifyloads its full details without showing "Could not load full details: Failed to fetch"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 failureSkillDetailcomponent used by every skill page; the regression tests use generic skillsasm installvisible, Try again refetches). CDP run with every request failing shows the sameabout:blankandPage.reloadeach issued the detail request (200) with no error; failures are never cached (detailCachestores successes only)