Skip to content

fix: add safety guards for paginated GitHub API requests#104

Open
KaranUnique wants to merge 2 commits into
AOSSIE-Org:mainfrom
KaranUnique:pagination-safety-guard
Open

fix: add safety guards for paginated GitHub API requests#104
KaranUnique wants to merge 2 commits into
AOSSIE-Org:mainfrom
KaranUnique:pagination-safety-guard

Conversation

@KaranUnique

@KaranUnique KaranUnique commented Jul 4, 2026

Copy link
Copy Markdown

Addressed Issues:

Fixes #103

Additional Notes:

fetchContributors and fetchIssues both used an unbounded for(let page = 1; ; page++) loop with no upper limit. If GitHub returned a malformed or non-array response (e.g. a rate-limit error object), data.length < 100 would never evaluate to true, causing an infinite loop and crashing the app.

Two guards were added to each function, placed at the top of the loop body before any data is consumed:

if (page > 50) break — hard cap at 50 pages (5,000 items max), consistent with the existing guard already present in fetchRepos.
if (!Array.isArray(data)) break — exits safely if the API returns anything other than an array (error object, rate-limit response, etc.), preventing the spread operator from throwing.

No behaviour changes for normal responses — the existing data.length < 100 early-exit still handles the happy path.

Checklist

  • My code follows the project's code style and conventions
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings or errors
  • I have joined the Discord server and I will share a link to this PR with the project maintainers there
  • I have read the Contributing Guidelines

⚠️ AI Notice - Important!

We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact.

Summary by CodeRabbit

  • Bug Fixes
    • Improved loading of contributors and issues so pagination stops safely after a large number of pages.
    • Added checks to handle unexpected response data more gracefully, reducing the chance of incomplete or broken results during data loading.

@github-actions github-actions Bot added bug Something isn't working javascript JavaScript/TypeScript changes labels Jul 4, 2026
@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@KaranUnique, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d2403615-d835-45c9-8fc2-1f60d9d6469b

📥 Commits

Reviewing files that changed from the base of the PR and between a9dd81a and 13c1114.

📒 Files selected for processing (1)
  • src/services/github.js

Walkthrough

The pagination loops in fetchContributors and fetchIssues within src/services/github.js are updated to cap requests at page 50 and validate that fetched data is an array before use, breaking early otherwise.

Changes

Pagination Safety Guard

Layer / File(s) Summary
Bounded pagination with array validation
src/services/github.js
Both fetchContributors and fetchIssues loops now stop once page > 50 and validate Array.isArray(data), breaking early when the response is not an array.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested labels: Typescript Lang

Poem

A hop, a skip, a page-count cap,
No more loops that fall in a trap.
If data's not an array, we halt with grace,
Fifty pages max, then we end the chase.
🐇✨ Safe and sound, my burrow's code!

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The change addresses issue #103 by capping pagination and validating API responses in both functions.
Out of Scope Changes check ✅ Passed The PR stays focused on pagination safety in services/github.js and adds no unrelated changes.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding safety guards to paginated GitHub API requests.
✨ 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.

@github-actions github-actions Bot added size/XS 1-10 lines changed first-time-contributor First time contributor and removed size/XS 1-10 lines changed labels Jul 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/services/github.js (1)

101-112: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract shared pagination logic to reduce duplication.

The page-cap and array-validation loop bodies are now identical between fetchContributors and fetchIssues, differing only by the URL template. Consider factoring this into a shared paginated-fetch helper to avoid maintaining two copies of the same safety logic.

♻️ Suggested refactor
+async function fetchAllPages(urlBuilder, pat) {
+  const all = []
+  for (let page = 1; page <= 50; page++) {
+    const data = await fetchWithCache(urlBuilder(page), pat)
+    if (!Array.isArray(data)) break
+    all.push(...data)
+    if (data.length < 100) break
+  }
+  return all
+}
+
 export async function fetchContributors(org, repo, pat) {
-  const all = []
-  for(let page = 1; ; page++) {
-    if (page > 50) break
-    const url = `https://api.github.com/repos/${org}/${repo}/contributors?per_page=100&page=${page}`
-    const data = await fetchWithCache(url, pat)
-    if (!Array.isArray(data)) break
-    all.push(...data)
-    if(data.length < 100) break
-  }
-  return all
+  return fetchAllPages(
+    page => `https://api.github.com/repos/${org}/${repo}/contributors?per_page=100&page=${page}`,
+    pat
+  )
 }

Also applies to: 114-125

🤖 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/services/github.js` around lines 101 - 112, `fetchContributors`
duplicates the same pagination and array-validation flow used by `fetchIssues`,
so extract that shared loop into a reusable helper and have both functions call
it with their URL template. Keep the existing safety checks (page cap,
`Array.isArray` guard, and stop-on-short-page behavior) inside the shared
helper, and update `fetchContributors` to only define the contributors URL and
delegate the rest.
🤖 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/services/github.js`:
- Line 107: The pagination loop in github.js silently exits when `data` is not
an array, which masks malformed or rate-limit responses as a normal
end-of-results condition. Update the `if (!Array.isArray(data)) break` path in
the relevant loop(s) to emit a warning (for example via `console.warn` or the
existing logger) with enough context to identify the unexpected payload before
breaking, keeping the behavior but making the failure visible.

---

Outside diff comments:
In `@src/services/github.js`:
- Around line 101-112: `fetchContributors` duplicates the same pagination and
array-validation flow used by `fetchIssues`, so extract that shared loop into a
reusable helper and have both functions call it with their URL template. Keep
the existing safety checks (page cap, `Array.isArray` guard, and
stop-on-short-page behavior) inside the shared helper, and update
`fetchContributors` to only define the contributors URL and delegate the rest.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: f916622b-7d34-418b-97b7-ba21e7f69c13

📥 Commits

Reviewing files that changed from the base of the PR and between d904719 and a9dd81a.

📒 Files selected for processing (1)
  • src/services/github.js

Comment thread src/services/github.js Outdated
@github-actions github-actions Bot added size/XS 1-10 lines changed and removed size/XS 1-10 lines changed labels Jul 4, 2026
@Ri1tik

Ri1tik commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Nice work @KaranUnique. Please attach before and after screen recording to review the outcomes.

@KaranUnique

Copy link
Copy Markdown
Author

@Ri1tik This fix addresses a defensive edge case rather than a visible UI behavior. Under normal GitHub API responses, the application behaves the same before and after. The added guards only prevent unexpected or malformed API responses from causing issues, so there isn't a meaningful visual difference to demonstrate in a screen recording

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

Labels

bug Something isn't working first-time-contributor First time contributor javascript JavaScript/TypeScript changes size/XS 1-10 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]: Missing pagination safety guard in fetchContributors() and fetchIssues()

2 participants