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

No fields configured for Feature.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions