Skip to content

Property PaginatedList.totalCount returns 0 when GitHub deprecation notices exists for API path #3379

@odedperezcodes

Description

@odedperezcodes

Summary

search_issues().totalCount incorrectly returns 0 instead of the actual count from GitHub API responses when GitHub includes deprecation notices in Link headers.

Environment

  • PyGithub Version: 2.8.1 (also affects 1.55 and likely all versions)
  • Python Version: 3.9.12
  • GitHub API: Enterprise GitHub (also affects github.com)

Problem Description

Since GitHub started including deprecation notices in Link headers (around early September 2025), PyGithub's search_issues() method incorrectly returns totalCount = 0 even when results exist.

Expected Behavior

issues = gh.search_issues("commit:EXAMPLE_COMMIT_SHA")
print(issues.totalCount)  # Should print: 1

Actual Behavior

issues = gh.search_issues("commit:EXAMPLE_COMMIT_SHA")
print(issues.totalCount)  # Actually prints: 0

Root Cause Analysis

File: github/PaginatedList.py, lines 152-165

The bug occurs in the totalCount property getter:

if "link" not in headers:  # Line 152 - ISSUE HERE
    # This path would correctly use data["total_count"]
    if data and "total_count" in data:
        self.__totalCount = data["total_count"]  # Would work correctly
else:
    # Takes this path due to deprecation Link header
    links = self.__parseLinkHeader(headers)
    lastUrl = links.get("last")  # Returns None (no pagination links)
    if lastUrl:
        self.__totalCount = int(parse_qs(lastUrl)["page"][0])
    else:
        self.__totalCount = 0  # BUG: Sets to 0 instead of using JSON total_count

The Issue: GitHub now includes deprecation notices in Link headers:

Link: <https://github.blog/changelog/2025-03-06-github-issues-projects-api-support-for-issues-advanced-search-and-more/>; rel="deprecation"; type="text/html"

PyGithub incorrectly assumes any Link header means pagination exists, but deprecation notices are not pagination links.

Reproduction Steps

  1. Make any search that returns results:

    curl -H "Authorization: token YOUR_TOKEN" \
         "https://api.github.com/search/issues?q=commit:EXAMPLE_COMMIT_SHA"

    Returns: {"total_count": 1, "items": [...]}

  2. Use PyGithub:

    import github
    from github import Auth
    
    auth = Auth.Token("YOUR_TOKEN")
    gh = github.Github(auth=auth)
    issues = gh.search_issues("commit:EXAMPLE_COMMIT_SHA")
    print(f"totalCount: {issues.totalCount}")  # Prints 0 instead of 1

Evidence

HTTP Response (captured with debugging):

{
  "total_count": 1,
  "incomplete_results": false,
  "items": [{"number": 12345, "title": "Example PR", ...}]
}

Response Headers:

Link: <https://github.blog/changelog/2025-03-06-github-issues-projects-api-support-for-issues-advanced-search-and-more/>; rel="deprecation"; type="text/html"

Parsed Links: {"deprecation": "https://github.blog/changelog/..."}
Result: No "last" link found → totalCount = 0

Proposed Fix

Change line 152 in PaginatedList.py from:

if "link" not in headers:

To:

if "link" not in headers or not self.__hasPaginationLinks(headers):

Where __hasPaginationLinks() checks for pagination-specific rel values ("next", "prev", "last", "first"), ignoring other Link types like deprecation notices.

Alternative implementation:

def __hasPaginationLinks(self, headers):
    """Check if Link header contains pagination links, not just deprecation notices"""
    if "link" not in headers:
        return False

    links = self.__parseLinkHeader(headers)
    pagination_rels = {"next", "prev", "last", "first"}
    return any(rel in pagination_rels for rel in links.keys())

Impact

This bug affects:

  • All search operations (search_issues, search_repositories, search_users, etc.)
  • Any application relying on search result counts
  • Pagination logic when GitHub includes deprecation notices

Additional Context: This issue started appearing around early September 2025 when GitHub began including deprecation notices in API responses, breaking existing PyGithub installations that were working fine before.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions