Skip to content

Add graceful fallback and logging for GitHub API rate-limiting during template fetch #970

@psmman

Description

@psmman

Problem

  • specify init fetches release data and downloads assets from the GitHub Releases API. If the API rate-limits (or returns an unexpected status), the current error output can be terse and does not expose helpful headers like X-RateLimit-Remaining, X-RateLimit-Reset, or the Retry-After header. This makes diagnosing transient network or rate-limit issues harder for users and maintainers.

Why this helps

  • Displaying the relevant GitHub rate-limit headers and providing a sensible fallback makes failures easier to understand and act on. A fallback can also attempt a short backoff/retry for transient rate-limits and print the time when the client can retry based on X-RateLimit-Reset.

Proposed change

  1. Add header-aware error reporting in download_template_from_github (or the HTTP helper used) so that when a non-200 response is received, the error panel includes:

    • status_code and brief reason (already present)
    • X-RateLimit-Limit (if present)
    • X-RateLimit-Remaining (if present)
    • X-RateLimit-Reset (if present)-convert epoch seconds to a human-readable timestamp in the user's local timezone
    • Retry-After (if present)
  2. If the response status indicates rate limiting (HTTP 429) or X-RateLimit-Remaining is 0, implement a simple optional retry strategy:

    • If Retry-After exists: sleep for that many seconds and retry once.
    • Else if X-RateLimit-Reset exists: calculate time until reset; if <= 30 seconds, sleep and retry once; otherwise print a message advising the user to retry later (display reset time).
    • Else: do not retry; surface an actionable error with header details and a troubleshooting hint.
  3. Improve user-facing message and troubleshooting panel to include the headers and a short guidance text such as:

    • "Tip: If you're on a shared CI or corporate environment, you may be rate-limited. Consider using a GitHub token via --github-token or the GH_TOKEN/GITHUB_TOKEN environment variable to increase rate limits."
  4. Optionally add a --retry-on-rate-limit flag to specify init (default: false) to allow users to opt-in to the automatic short retry behavior. The flag could be useful for automation contexts where waiting a few seconds is acceptable.

Suggested patch outline

  • In src/specify_cli/__init__.py inside download_template_from_github:
    • After receiving the HTTP response, capture headers = response.headers.
    • On non-200, create a helpful detail string composed of the status and any present headers listed above.
    • If status is 429 or X-RateLimit-Remaining == '0', follow the retry decision tree described above.
    • Use rich.Panel to display headers and guidance text when raising errors.

Testing notes

  • Unit test: mock github API responses for the following cases and assert behavior/printed output:
    • 200 OK (no change)
    • 403 or 429 with X-RateLimit-Remaining: 0 and X-RateLimit-Reset in near future (simulate retry path)
    • 403 or 429 with Retry-After header (simulate retry path)
    • 403 or 429 with no rate-limit headers (assert no retry and helpful error)
  • Integration test: run download_template_from_github against a local HTTP server that returns rate-limit headers to validate user-visible messages.

You can use this for additional documentation:

  • Keep retries conservative (single short retry) to avoid long blocking behavior or masking larger rate-limit issues.
  • Prefer explicit guidance to using a GitHub token rather than silently retrying indefinitely.

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions