unslothai/unsloth · critical · GitHubAuthError
GitHub {endpoint} returned {r.status_code} {r.reason}. Token
Error message
GitHub {endpoint} returned {r.status_code} {r.reason}. Token source: {self._token_source}. The token is invalid, expired, or missing required scopes — retrying will not recover.{request_id_message} Response: {snippet} What it means
GitHubAuthError raised by _raise_auth_error for GitHub responses where the client determined the failure is non-retryable: HTTP 401 always, and 403 only when it is NOT a rate-limit response (checked via Retry-After / X-RateLimit-Remaining: 0 / abuse detection text). The message includes the endpoint, status, token source, GitHub request ID, and first 200 bytes of the response body so the user can diagnose scope/expiry issues. Retrying will not help — the token itself is bad.
Source
Thrown at studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py:128
)
def _is_auth_failure(self, r: "requests.Response") -> bool:
"""Tell auth failures apart from rate limiting on 401/403.
401 is always auth; 403 is auth unless it carries a rate-limit signal
(Retry-After, X-RateLimit-Remaining: 0, or abuse/secondary text).
"""
if r.status_code == 401:
return True
if r.status_code == 403:
return not self._is_rate_limit_response(r)
return False
def _raise_auth_error(self, r: "requests.Response", endpoint: str) -> None:
snippet = (r.text or "").strip()[:200]
request_id = r.headers.get("X-GitHub-Request-Id")
request_id_message = f" Request ID: {request_id}." if request_id else ""
raise GitHubAuthError(
f"GitHub {endpoint} returned {r.status_code} {r.reason}. "
f"Token source: {self._token_source}. "
f"The token is invalid, expired, or missing required scopes — "
f"retrying will not recover.{request_id_message} Response: {snippet}"
)
def _check_rate_and_wait(self, kind: str) -> None:
if kind == "graphql":
remaining = self.graphql_remaining
reset = self.graphql_reset
min_remaining = self.min_remaining_graphql
else:
remaining = self.rest_remaining
reset = self.rest_reset
min_remaining = self.min_remaining_rest
if remaining is not None and remaining < min_remaining:
if reset:
self._sleep_until(reset)View on GitHub (pinned to 203007d190)
Solutions
- Regenerate or extend the token and update GH_TOKEN/GITHUB_TOKEN (or the recipe token field).
- For fine-grained PATs, grant access to the specific repos/orgs and required permissions (contents, issues, pull requests read).
- For org repos, authorize the token for SSO/SAML in GitHub settings if the org enforces it.
- Use the Request ID in the message when contacting GitHub support.
Example fix
# before export GH_TOKEN="ghp_expiredtoken..." # after # create a fresh token with repo scope at https://github.com/settings/tokens export GH_TOKEN="ghp_newtoken..."
Defensive patterns
Strategy: try-catch
Try / catch
from data_designer_github_repo_seed.scraper_impl.gh_client import GitHubAuthError
try:
client.fetch_repo_issues("owner/name")
except GitHubAuthError as e:
msg = str(e)
if "401" in msg or "403" in msg:
# non-retryable: rotate/fix the token, check scopes/SSO, then re-run
report_fatal_auth(msg) # includes token source + GitHub Request ID
raise Prevention
- Preflight the token with a cheap authenticated call (GET /user) before starting a long scrape.
- Use fine-grained PATs granted to the exact orgs with the permissions the scraper needs (contents/issues/PRs read).
- Record the token source and GitHub Request ID from the message when escalating.
When it happens
Trigger: Any GraphQL or REST call returning 401 (bad/expired/revoked token), or 403 for reasons other than rate limiting (SSO authorization missing, fine-grained PAT without access to the org/repo, missing scope like repo for a private repo).
Common situations: Token expired or revoked between runs; fine-grained PAT not granted to the target organization or lacking the 'contents:read' scope; organization requires SSO/SAML authorization the PAT never received; classic PAT without repo scope hitting private repos.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Invalid or expired token
- Invalid or expired API key
- Invalid token payload
- GitHub token is required. Set it in the recipe config or the
- GH_TOKEN or GITHUB_TOKEN not set in environment
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/42bc43cf702d64ad.
Report an issue: GitHub.