🐛 Fix active-users HTML parse errors on Netlify#4325
Conversation
On Netlify (no Go backend), /api/active-users falls through to the SPA catch-all redirect returning index.html. MSW should intercept these, but there's a timing gap during MSW startup where fetches fire before the service worker registers. The fetch code then tries to parse HTML as JSON, causing repeated `SyntaxError: Unexpected token '<'` console errors every minute. Fix: Check response content-type before attempting JSON parse. If the response is not application/json (e.g., text/html from the SPA fallback), treat it as an error without attempting to parse. Signed-off-by: Andrew Anderson <andy@clubanderson.com>
|
/lgtm |
|
@clubanderson: you cannot LGTM your own PR. DetailsIn response to this:
Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. |
|
👋 Hey @clubanderson — thanks for opening this PR!
This is an automated message. |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: clubanderson The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
✅ Deploy Preview for kubestellarconsole ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
Fixes recurring SyntaxError: Unexpected token '<' console noise on Netlify (console.kubestellar.io) by preventing the /api/active-users hook from attempting response.json() when the response is actually HTML (SPA catch-all index.html).
Changes:
- Add an
isJsonResponse()content-type guard inuseActiveUsersto skip JSON parsing on non-JSON responses. - Update existing unit tests to include
Content-Type: application/jsonon mocked successful responses. - Add a unit test case for the HTML fallback scenario.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
web/src/hooks/useActiveUsers.ts |
Adds a content-type guard to avoid calling resp.json() on HTML fallback responses. |
web/src/hooks/__tests__/useActiveUsers.test.ts |
Updates fetch mocks to set JSON content-type and adds an HTML-fallback test case. |
| // --- Handles HTML fallback response (Netlify SPA catch-all) --- | ||
| it('handles HTML response without SyntaxError (Netlify SPA fallback)', async () => { | ||
| vi.mocked(fetch).mockResolvedValue( | ||
| new Response('<!doctype html><html><body>SPA</body></html>', { | ||
| status: 200, | ||
| headers: { 'Content-Type': 'text/html' }, | ||
| }) | ||
| ) | ||
|
|
||
| const { result } = renderHook(() => useActiveUsers()) | ||
| await act(async () => { await vi.advanceTimersByTimeAsync(100) }) | ||
|
|
||
| // Should not crash or throw SyntaxError — gracefully treated as error | ||
| expect(typeof result.current.activeUsers).toBe('number') | ||
| }) |
There was a problem hiding this comment.
The new HTML-fallback test doesn’t actually validate the behavior introduced by this PR. It would have passed even before the isJsonResponse() guard because resp.json().catch(() => null) already prevents the SyntaxError from failing the test. Consider asserting that json() is not called for a text/html response (e.g., return a minimal Response-like mock with headers.get() and a json spy) so the test fails if JSON parsing is attempted again.
🔄 Auto-Applying Copilot Code ReviewCopilot code review found 0 code suggestion(s) and 1 general comment(s). Also address these general comments:
Push all fixes in a single commit. Run Auto-generated by copilot-review-apply workflow. |
|
Thank you for your contribution! Your PR has been merged. Check out what's new:
Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey |
Summary
On
console.kubestellar.io(Netlify),/api/active-usersfalls through to the SPA catch-all redirect during MSW startup, returningindex.htmlas a 200 response. The hook tries to parse this as JSON →SyntaxError: Unexpected token '<'every minute in the console.Fix
Added
isJsonResponse()guard that checkscontent-typeheader before attemptingres.json(). Non-JSON responses (HTML fallback) are treated as errors without parse attempt.Test plan
Unexpected token '<'errors on console.kubestellar.io