Skip to content

bug: version discovery fails once the anonymous github api quota is spent #298

Description

@0xKT

Symptom

Once the GitHub API's anonymous quota is spent for the caller's IP, two entry points break:

  • raven upgrade reports Client error '403 Forbidden' ... For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/403. Check your network and try again, which points at the wrong problem: the network is fine and the MDN page for 403 describes a permission error, while the repository is public.
  • curl | sh fails with Could not resolve the latest raven release wheel from GitHub (check network, ...), with no indication of the real cause.

Neither message mentions a quota, when it resets, or that a token raises it.

Root cause

Version discovery only ever calls api.github.com:

  • raven/cli/upgrade_commands.py:234 sends Accept, User-Agent and X-GitHub-Api-Version, but no Authorization.
  • install.sh:192 and install.ps1:197 are anonymous as well.

Unauthenticated REST calls are capped at 60 requests per hour and the bucket is keyed on the source IP, so every person, CI runner and polling script behind one NAT egress shares the same 60. Measured on our egress:

x-ratelimit-limit: 60
x-ratelimit-remaining: 0
x-ratelimit-used: 60
x-ratelimit-resource: core
x-ratelimit-reset: <epoch>

The failure surface is narrower than it looks: only version discovery is affected. The wheel and raven-constraints.txt come from github.com/.../releases/download/..., which does not consume the core API quota, so the accurate description is "cannot find out whether a newer version exists", not "cannot download it".

Second defect: the advice is unconditional

raven/cli/upgrade_commands.py:453 catches transport errors, HTTP status errors and UpgradeError in one branch and appends Check your network and try again; if the problem persists, rerun the official installer. to all of them. Two consequences:

  • a 403 for a spent quota is reported as a network problem;
  • errors that have nothing to do with the network get the same sentence, down to Editable Raven installations cannot be upgraded automatically. Pull the source checkout and rebuild Raven.. Check your network and try again (note the double period, also present today).

The information needed to report this correctly is already in hand and simply never read: httpx keeps the response on the exception, so exc.response carries GitHub's own API rate limit exceeded message and the x-ratelimit-reset timestamp. httpx builds its exception string from a fixed template (status line plus an MDN link) and never includes the body, so f"{exc}" cannot show them.

Reproduction without spending the quota

A local HTTP server replaying GitHub's spent-quota 403 (same body, same five x-ratelimit-* headers) is enough; point only the API endpoint at it and let everything else reach real GitHub. Against the current code that reproduces the misleading message exactly.

Proposed fix

  1. Back the API up with the release page. github.com/<owner>/<repo>/releases/latest redirects to /releases/tag/vX.Y.Z and carries no API quota; the wheel URL is then derived from the same shape the payload validator already enforces, so no new trust is introduced. Only transport and status failures fall back: a payload that parsed as draft or prerelease must never be routed around, because the release page cannot re-check those flags.
  2. Separate remote release-lookup failures from local installation failures, so a spent quota reports the quota facts and the reset time, network advice appears only when both paths failed at the transport layer, and the installer hint stays where it applies.
  3. Apply the same fallback to install.sh and install.ps1, keeping one URL shape across all three callers.

Out of scope

Reading GITHUB_TOKEN / GH_TOKEN to raise the limit to 5000/hour. It only helps callers that already have a token (CI, developer machines) and does nothing for the ordinary user who hits this, so it belongs in its own change rather than being mistaken for the fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions