{"record":{"id":"d2f30dd903accd57","repo":"rahuldkjain/github-profile-readme-generator","slug":"failed-to-fetch-stats-response-status","errorCode":null,"errorMessage":"Failed to fetch stats (${response.status})","messagePattern":"Failed to fetch stats \\((.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/components/ui/github-stats.tsx","lineNumber":45,"sourceCode":"    const fetchStats = async () => {\n      if (!shouldRequestStats()) return;\n\n      try {\n        const response = await fetch(\n          'https://api.github.com/repos/rahuldkjain/github-profile-readme-generator'\n        );\n\n        if (!response.ok) {\n          if (response.status === 403) {\n            const rateLimitRemaining = response.headers.get('X-RateLimit-Remaining');\n            if (rateLimitRemaining === '0') {\n              console.warn('GitHub API rate limit exceeded for stats');\n              setError(true);\n              setIsLoading(false);\n              return;\n            }\n          }\n          throw new Error(`Failed to fetch stats (${response.status})`);\n        }\n\n        const data = await response.json();\n        setStats({\n          stars: data.stargazers_count || 0,\n          forks: data.forks_count || 0,\n        });\n        setIsLoading(false);\n      } catch (err) {\n        console.error('Error fetching GitHub stats:', err);\n        setError(true);\n        setIsLoading(false);\n\n        // Only show error toast on first load, not on periodic refreshes\n        if (stats === null) {\n          errorToast(\n            'Failed to load GitHub stats',\n            \"Unable to fetch repository statistics. This won't affect the generator functionality.\",","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/rahuldkjain/github-profile-readme-generator/blob/5ae90bfcbd7ab2f69809b094601f7975c32ae077/src/components/ui/github-stats.tsx#L27-L63","documentation":"fetchStats throws this generic Error whenever the GitHub REST API returns a non-ok HTTP status that is not the handled rate-limit case (403 with X-RateLimit-Remaining: 0). The component calls the unauthenticated endpoint https://api.github.com/repos/rahuldkjain/github-profile-readme-generator to display star/fork counts, and any unexpected status (404, 5xx, 403 without rate-limit header, etc.) becomes this error. It is caught by the component itself, which sets an error state, hides the widget, and shows a toast on first load.","triggerScenarios":"GitHub returns any non-2xx status other than rate-limited 403: e.g. 404 if the repo slug is wrong or renamed, 502/503 when GitHub API is degraded, 403 blocked by a proxy/CDN or for abuse without X-RateLimit-Remaining: 0, or 451 for region-blocked content.","commonSituations":"Developers hit this when the repository was renamed/made private (404), when GitHub has a partial outage (5xx), when a corporate proxy or ad-blocker rewrites api.github.com responses, or when the unauthenticated 60 req/hour rate limit is hit but the X-RateLimit-Remaining header is stripped by a proxy so the special 403 branch is missed. It also fires in local dev behind firewalls blocking api.github.com.","solutions":["Open the browser network tab and read the actual status code in the message (e.g. 404 vs 503) to identify the real cause before changing code.","If status is 404, verify the repo path 'rahuldkjain/github-profile-readme-generator' is correct, public, and not renamed; update the hardcoded URL if you forked/renamed it.","If status is 403/429, check the X-RateLimit-Remaining and X-RateLimit-Reset headers; unauthenticated GitHub API allows only ~60 requests/hour per IP, and this component polls every 60 seconds.","Reduce the polling interval (setInterval(fetchStats, 60000)) or cache stats server-side to stay under the rate limit.","For 5xx statuses, simply retry later or add exponential backoff; the error is transient on GitHub's side.","Check for proxies/ad-blockers/extensions intercepting api.github.com and stripping headers or blocking the request."],"exampleFix":"// before\nthrow new Error(`Failed to fetch stats (${response.status})`);\n// after\nif (response.status === 404) {\n  console.error('Repo not found: check the repository slug in the fetch URL');\n}\nthrow new Error(`Failed to fetch stats (${response.status})`);","handlingStrategy":"try-catch","validationCode":"const res = await fetch('https://api.github.com/repos/rahuldkjain/github-profile-readme-generator', { method: 'HEAD' });\nif (!res.ok) console.warn(`GitHub API unavailable (status ${res.status}); skipping stats fetch`);","typeGuard":"function isGitHubStats(data: unknown): data is { stargazers_count: number; forks_count: number } {\n  return typeof data === 'object' && data !== null &&\n    'stargazers_count' in data && typeof (data as any).stargazers_count === 'number' &&\n    'forks_count' in data && typeof (data as any).forks_count === 'number';\n}","tryCatchPattern":"try {\n  const response = await fetch('https://api.github.com/repos/owner/repo');\n  if (!response.ok) {\n    if (response.status === 403 && response.headers.get('X-RateLimit-Remaining') === '0') {\n      return null; // treat rate limit as silent fallback\n    }\n    throw new Error(`Failed to fetch stats (${response.status})`);\n  }\n  const data = await response.json();\n  return { stars: data.stargazers_count, forks: data.forks_count };\n} catch (err) {\n  console.warn('GitHub stats unavailable, using fallback:', err);\n  return null; // render widget with cached/default values instead of erroring\n}","preventionTips":["Cache GitHub stats server-side or in localStorage instead of polling the API every 60 seconds from the client.","Include a GitHub token (via a server-side proxy, never in client code) to raise the rate limit from 60 to 5000 requests/hour.","Always check response.ok before calling response.json() on any fetch.","Handle 403 with the X-RateLimit-Remaining header explicitly, as this component does, and back off using X-RateLimit-Reset.","Render the widget defensively (return null or cached values on failure) so a stats failure never breaks the page."],"tags":["http","github-api","fetch","network","rate-limit"],"backgroundTag":"http-non-ok-response","analyzedSha":"5ae90bfcbd7ab2f69809b094601f7975c32ae077","analyzedAt":"2026-08-31T14:37:06.401Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}