Skip to content

Add GitHub API rate limit handling UI#560

Open
vivekktrivedi06-hue wants to merge 1 commit into
GitMetricsLab:mainfrom
vivekktrivedi06-hue:fix/github-rate-limit-ui
Open

Add GitHub API rate limit handling UI#560
vivekktrivedi06-hue wants to merge 1 commit into
GitMetricsLab:mainfrom
vivekktrivedi06-hue:fix/github-rate-limit-ui

Conversation

@vivekktrivedi06-hue
Copy link
Copy Markdown

@vivekktrivedi06-hue vivekktrivedi06-hue commented May 27, 2026

📌 Description

This PR adds proper handling for GitHub API rate limit errors.

✨ Changes

  • Detects 403 rate limit errors
  • Shows user-friendly message
  • Displays remaining requests and reset time

🔗 Related Issue

Fixes #496

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved error handling for GitHub API requests with more descriptive error messages.
    • Added rate-limit detection that displays retry timing when API limits are reached.
  • UI Improvements

    • Enhanced loading and error states with better visual feedback on the Contributors page.

Review Change Stack

@netlify
Copy link
Copy Markdown

netlify Bot commented May 27, 2026

Deploy Preview for github-spy ready!

Name Link
🔨 Latest commit a1f12a3
🔍 Latest deploy log https://app.netlify.com/projects/github-spy/deploys/6a16a656ac947e00089774d4
😎 Deploy Preview https://deploy-preview-560--github-spy.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 27, 2026

📝 Walkthrough

Walkthrough

ContributorsPage enhances its GitHub API fetch with detailed error handling that detects 403 rate-limit responses, reads rate-limit headers, and displays user-friendly messages. The component rendering is reorganized with early-return UI branches for loading and error states before displaying the contributors grid.

Changes

GitHub Contributors Rate-Limit Error Handling

Layer / File(s) Summary
Rate-limit error detection and messaging
src/pages/Contributors/Contributors.tsx
Axios error handling checks HTTP status codes; 403 responses parse x-ratelimit-remaining and x-ratelimit-reset headers to build "try again after …" messages; other failures set generic "failed to fetch" or "unexpected error" messages. Includes commented temporary testing code for exercising rate-limit UI.
Loading and error state UI rendering
src/pages/Contributors/Contributors.tsx
Component render branches with early-return loading state (MUI CircularProgress) and error state (MUI Alert) before main page content; contributors grid continues to render route-linked cards and external GitHub button with updated JSX layout; module default export.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • GitMetricsLab/github_tracker#411: Modifies the same ContributorsPage component including contributors fetching logic and render UI branches (loading/error/grid display).

Suggested labels

level:intermediate, quality:clean

Poem

🐰 A rabbit bounds through GitHub's halls,
Rate limits! Errors! API calls!
Now when 403 blocks the way,
We show the time to try today. 🕐✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description deviates from the template structure; it lacks required sections like 'Related Issue' header format, 'How Has This Been Tested?', 'Screenshots', and 'Type of Change' checkbox selections. Restructure the description to follow the template: add 'Related Issue' section with proper format, include 'How Has This Been Tested?' section, add 'Screenshots' section, and select appropriate 'Type of Change' checkboxes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding GitHub API rate limit handling UI, which aligns with the primary objective.
Linked Issues check ✅ Passed The PR implements all coding requirements from issue #496: detects 403 rate limit errors, displays user-friendly messages, shows remaining request counts, and displays reset times via rate-limit headers.
Out of Scope Changes check ✅ Passed All changes in Contributors.tsx are directly related to implementing GitHub API rate limit handling as specified in issue #496; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/pages/Contributors/Contributors.tsx (1)

46-65: ⚡ Quick win

Remove temporary commented test code from the component.

This debug block adds noise in production code and is easy to forget during future edits. Prefer keeping this in tests or local-only mocks.

Proposed cleanup
-        /*
-        // ==================================================
-        // TEMPORARY TESTING CODE
-        // Uncomment this block ONLY if you want to test
-        // the rate limit UI manually.
-        // ==================================================
-
-        // // throw {
-        // //   isAxiosError: true,
-        // //   response: {
-        // //     status: 403,
-        // //     headers: {
-        // //       "x-ratelimit-remaining": 0,
-        // //       "x-ratelimit-reset": 1750000000,
-        // //     },
-        // //   },
-        // // };
-
-        // ==================================================
-        // */
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/Contributors/Contributors.tsx` around lines 46 - 65, Remove the
temporary commented-out testing block in Contributors.tsx (the multi-line
comment that contains the simulated Axios rate-limit throw) from the
Contributors component file; locate the commented section between the marker
lines "TEMPORARY TESTING CODE" and the closing "*/" and delete it so only
production code remains, or move any necessary test logic into dedicated
test/mocks rather than leaving commented debug code in Contributors.tsx.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pages/Contributors/Contributors.tsx`:
- Around line 223-225: The anchor rendered for contributors uses target="_blank"
on href={contributor.html_url} (in Contributors.tsx) without a rel attribute;
update the Link/anchor element that sets href={contributor.html_url} and
target="_blank" to also include rel="noopener noreferrer" to prevent tab-napping
and improve security (ensure the change is applied where the contributor link is
created, e.g., the element rendering contributor.html_url).
- Around line 70-91: The code currently assumes any HTTP 403 is a GitHub
rate-limit and directly interpolates headers that may be absent; update the 403
branch in the Contributors component to first check for the presence of
rate-limit headers (error.response.headers["x-ratelimit-remaining"] and
["x-ratelimit-reset"]) and only treat it as a rate-limit when the headers exist,
otherwise setError to a generic 403 authorization/permission message that
includes safe fallbacks (e.g., statusText or error.message) instead of
interpolating undefined; when building the rate-limit message use a default
value (like "unknown" or "N/A") for remaining and only compute/resetMessage if
x-ratelimit-reset is present before calling setError.

---

Nitpick comments:
In `@src/pages/Contributors/Contributors.tsx`:
- Around line 46-65: Remove the temporary commented-out testing block in
Contributors.tsx (the multi-line comment that contains the simulated Axios
rate-limit throw) from the Contributors component file; locate the commented
section between the marker lines "TEMPORARY TESTING CODE" and the closing "*/"
and delete it so only production code remains, or move any necessary test logic
into dedicated test/mocks rather than leaving commented debug code in
Contributors.tsx.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 44ce97d8-2ea5-48c3-88b8-0b134eab9987

📥 Commits

Reviewing files that changed from the base of the PR and between 4ae0ef6 and a1f12a3.

📒 Files selected for processing (1)
  • src/pages/Contributors/Contributors.tsx

Comment on lines +70 to +91
if (error.response?.status === 403) {

const remaining =
error.response.headers["x-ratelimit-remaining"];

const reset =
error.response.headers["x-ratelimit-reset"];

let resetMessage = "";

if (reset) {
const resetTime = new Date(
Number(reset) * 1000
);

resetMessage =
` Try again after ${resetTime.toLocaleTimeString()}.`;
}

setError(
`GitHub API rate limit exceeded. Remaining requests: ${remaining}.${resetMessage}`
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In GitHub REST API, are all HTTP 403 responses considered rate-limit errors? What is the recommended way to distinguish rate-limit responses (e.g., x-ratelimit-remaining/reset headers and response message) from other forbidden responses?

💡 Result:

No, not all HTTP 403 (Forbidden) responses from the GitHub REST API are caused by rate-limit errors [1][2]. A 403 status code is a general response indicating that the server refuses to authorize the request, which can occur due to insufficient permissions, invalid credentials, or other access-related issues, in addition to both primary and secondary rate limiting [1][3][4]. To distinguish a rate-limit error from other types of 403 Forbidden responses, you should examine the response body and specific HTTP headers [1][3][5]. Recommended approach to identify and handle rate limits: 1. Check the response body: GitHub explicitly includes information in the error message when a rate limit has been exceeded [1][3]. For example, messages regarding secondary rate limits will explicitly state that a secondary rate limit was exceeded [1][3]. 2. Check for the Retry-After header: If this header is present, it is a strong indicator that you have hit a rate limit (typically a secondary rate limit), and the value specifies how many seconds you must wait before retrying [1][3][5]. 3. Check x-ratelimit-remaining: If the x-ratelimit-remaining header is 0, it confirms that your primary rate limit has been exhausted [1][3][5]. The x-ratelimit-reset header will provide the UTC epoch time when your limit will reset [1][3][5]. If a 403 response does not contain these specific rate-limit indicators, it is likely a standard authorization or permission error [2][6][4]. In such cases, retrying will not resolve the issue and may be considered abusive behavior [1][5]. For rate-limit errors, follow the prescribed backoff strategies—such as waiting until the time specified by the x-ratelimit-reset header or using exponential backoff if a retry-after header is present—to remain compliant and avoid potential banning of your integration [1][3][5].

Citations:


Avoid mislabeling all GitHub 403s as rate limits (and prevent undefined in error text)

At src/pages/Contributors/Contributors.tsx (lines 70-91), the code treats every 403 as a rate-limit issue, but GitHub can return 403 for many non-rate-limit authorization/permission problems. Also, it interpolates x-ratelimit-remaining directly, which can show undefined to users when the header isn’t present.

Proposed hardening
-          if (error.response?.status === 403) {
-            const remaining =
-              error.response.headers["x-ratelimit-remaining"];
-            const reset =
-              error.response.headers["x-ratelimit-reset"];
+          if (error.response?.status === 403) {
+            const remainingHeader =
+              error.response.headers["x-ratelimit-remaining"];
+            const resetHeader =
+              error.response.headers["x-ratelimit-reset"];
+            const message = String(error.response.data?.message ?? "").toLowerCase();
+            const isRateLimit =
+              remainingHeader === "0" || message.includes("rate limit");
+
+            if (!isRateLimit) {
+              setError("Access forbidden. Please verify permissions and try again.");
+              return;
+            }

             let resetMessage = "";
-
-            if (reset) {
+            if (resetHeader && !Number.isNaN(Number(resetHeader))) {
               const resetTime = new Date(
-                Number(reset) * 1000
+                Number(resetHeader) * 1000
               );
               resetMessage =
                 ` Try again after ${resetTime.toLocaleTimeString()}.`;
             }

             setError(
-              `GitHub API rate limit exceeded. Remaining requests: ${remaining}.${resetMessage}`
+              `GitHub API rate limit exceeded. Remaining requests: ${remainingHeader ?? "unknown"}.${resetMessage}`
             );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (error.response?.status === 403) {
const remaining =
error.response.headers["x-ratelimit-remaining"];
const reset =
error.response.headers["x-ratelimit-reset"];
let resetMessage = "";
if (reset) {
const resetTime = new Date(
Number(reset) * 1000
);
resetMessage =
` Try again after ${resetTime.toLocaleTimeString()}.`;
}
setError(
`GitHub API rate limit exceeded. Remaining requests: ${remaining}.${resetMessage}`
);
if (error.response?.status === 403) {
const remainingHeader =
error.response.headers["x-ratelimit-remaining"];
const resetHeader =
error.response.headers["x-ratelimit-reset"];
const message = String(error.response.data?.message ?? "").toLowerCase();
const isRateLimit =
remainingHeader === "0" || message.includes("rate limit");
if (!isRateLimit) {
setError("Access forbidden. Please verify permissions and try again.");
return;
}
let resetMessage = "";
if (resetHeader && !Number.isNaN(Number(resetHeader))) {
const resetTime = new Date(
Number(resetHeader) * 1000
);
resetMessage =
` Try again after ${resetTime.toLocaleTimeString()}.`;
}
setError(
`GitHub API rate limit exceeded. Remaining requests: ${remainingHeader ?? "unknown"}.${resetMessage}`
);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/Contributors/Contributors.tsx` around lines 70 - 91, The code
currently assumes any HTTP 403 is a GitHub rate-limit and directly interpolates
headers that may be absent; update the 403 branch in the Contributors component
to first check for the presence of rate-limit headers
(error.response.headers["x-ratelimit-remaining"] and ["x-ratelimit-reset"]) and
only treat it as a rate-limit when the headers exist, otherwise setError to a
generic 403 authorization/permission message that includes safe fallbacks (e.g.,
statusText or error.message) instead of interpolating undefined; when building
the rate-limit message use a default value (like "unknown" or "N/A") for
remaining and only compute/resetMessage if x-ratelimit-reset is present before
calling setError.

Comment on lines +223 to +225
href={contributor.html_url}
target="_blank"
sx={{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add rel on the external link opened in a new tab.

Line 224 uses target="_blank" without rel="noopener noreferrer", which is a security gap.

Proposed fix
                   <Button
                     variant="contained"
                     startIcon={<FaGithub />}
                     href={contributor.html_url}
                     target="_blank"
+                    rel="noopener noreferrer"
                     sx={{
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
href={contributor.html_url}
target="_blank"
sx={{
href={contributor.html_url}
target="_blank"
rel="noopener noreferrer"
sx={{
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/Contributors/Contributors.tsx` around lines 223 - 225, The anchor
rendered for contributors uses target="_blank" on href={contributor.html_url}
(in Contributors.tsx) without a rel attribute; update the Link/anchor element
that sets href={contributor.html_url} and target="_blank" to also include
rel="noopener noreferrer" to prevent tab-napping and improve security (ensure
the change is applied where the contributor link is created, e.g., the element
rendering contributor.html_url).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

🚀 Feature: Add GitHub API Rate Limit Handling UI

1 participant