unslothai/unsloth · error · RuntimeError
GraphQL failed after {max_retries} retries: {last_err}
Error message
GraphQL failed after {max_retries} retries: {last_err} What it means
RuntimeError raised after the GraphQL request exhausts max_retries attempts. Each attempt that fails with a requests.RequestException (connection error, timeout, DNS failure) is logged, followed by exponential backoff (doubling, capped at 60s); after the final attempt the last exception is re-raised wrapped in this message. Note: GraphQL-level errors inside a 200 response are treated differently — rate-limit errors trigger retry, others are logged and partial data returned, so this error specifically means transport-level failures.
Source
Thrown at studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py:221
if "errors" in data and data["errors"]:
# Allow partial data; retry on RATE_LIMITED
errs = data["errors"]
for e in errs:
if e.get("type") == "RATE_LIMITED":
self._sleep_until((self.graphql_reset or int(time.time()) + 60))
break
else:
# No rate-limit error: log and return partial
log.warning("GraphQL errors: %s", json.dumps(errs)[:400])
return data
continue
return data
except requests.RequestException as e:
last_err = e
log.warning("GraphQL network error: %s. Retry.", e)
time.sleep(backoff)
backoff = min(backoff * 2, 60)
raise RuntimeError(f"GraphQL failed after {max_retries} retries: {last_err}")
def rest(
self,
method: str,
path: str,
params: Optional[Dict[str, Any]] = None,
json_body: Optional[Dict[str, Any]] = None,
max_retries: int = 6,
) -> requests.Response:
self._check_rate_and_wait("rest")
if path.startswith("http"):
url = path
else:
url = REST_BASE + path
backoff = 2
last_err = None
for attempt in range(max_retries):
try:View on GitHub (pinned to 203007d190)
Solutions
- Check basic connectivity: curl -sS https://api.github.com from the same host/container.
- Fix proxy/DNS configuration (HTTP_PROXY/HTTPS_PROXY, resolv.conf) so api.github.com is reachable.
- Re-run the job once the network is stable; the scraper is resumable across runs via its cache.
- If the environment is flaky by design, raise max_retries when calling graphql().
Example fix
# before $ python scrape.py # RuntimeError: GraphQL failed after 6 retries: ...ProxyError... # after $ unset HTTP_PROXY HTTPS_PROXY # or fix proxy to allow api.github.com $ python scrape.py
Defensive patterns
Strategy: retry
Validate before calling
import socket
def github_api_reachable(timeout: float = 5.0) -> bool:
try:
socket.create_connection(("api.github.com", 443), timeout=timeout).close()
return True
except OSError:
return False Try / catch
try:
data = client.graphql(query)
except RuntimeError as e:
if "GraphQL failed after" in str(e):
# transient transport failure: back off and restart the job (cache resumes)
time.sleep(300)
restart_job()
else:
raise Prevention
- Run a connectivity preflight to api.github.com before long scrape jobs.
- Schedule scrapes to rerun on RuntimeError-with-retries rather than treating it as data corruption.
- Keep the scraper's cache directory so restarts skip already-fetched pages.
When it happens
Trigger: Network outage, proxy/DNS failure, firewall blocking api.github.com, or TLS interception failing — repeatedly — for the whole retry window (6 attempts with exponential backoff).
Common situations: Corporate proxies blocking api.github.com; transient ISP/DNS problems during long scrape runs; container with broken resolv.conf; GitHub itself briefly unreachable from the runner's network.
Related errors
- REST failed after {max_retries} retries: {last_err}
- VirusTotal upload failed after {attempts} attempt(s): {last_
- Could not reach ChatGPT authentication.
- Could not refresh ChatGPT authorization. Please retry.
- Could not reach ChatGPT Codex.
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/f8733b2efd587184.
Report an issue: GitHub.