{"record":{"id":"f8733b2efd587184","repo":"unslothai/unsloth","slug":"graphql-failed-after-max-retries-retries-last","errorCode":null,"errorMessage":"GraphQL failed after {max_retries} retries: {last_err}","messagePattern":"GraphQL failed after (.+?) retries: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py","lineNumber":221,"sourceCode":"                if \"errors\" in data and data[\"errors\"]:\n                    # Allow partial data; retry on RATE_LIMITED\n                    errs = data[\"errors\"]\n                    for e in errs:\n                        if e.get(\"type\") == \"RATE_LIMITED\":\n                            self._sleep_until((self.graphql_reset or int(time.time()) + 60))\n                            break\n                    else:\n                        # No rate-limit error: log and return partial\n                        log.warning(\"GraphQL errors: %s\", json.dumps(errs)[:400])\n                        return data\n                    continue\n                return data\n            except requests.RequestException as e:\n                last_err = e\n                log.warning(\"GraphQL network error: %s. Retry.\", e)\n                time.sleep(backoff)\n                backoff = min(backoff * 2, 60)\n        raise RuntimeError(f\"GraphQL failed after {max_retries} retries: {last_err}\")\n\n    def rest(\n        self,\n        method: str,\n        path: str,\n        params: Optional[Dict[str, Any]] = None,\n        json_body: Optional[Dict[str, Any]] = None,\n        max_retries: int = 6,\n    ) -> requests.Response:\n        self._check_rate_and_wait(\"rest\")\n        if path.startswith(\"http\"):\n            url = path\n        else:\n            url = REST_BASE + path\n        backoff = 2\n        last_err = None\n        for attempt in range(max_retries):\n            try:","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/unslothai/unsloth/blob/203007d19051dcd2ae33876786d117c99f6b0368/studio/backend/plugins/data-designer-github-repo-seed/src/data_designer_github_repo_seed/scraper_impl/gh_client.py#L203-L239","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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()."],"exampleFix":"# before\n$ python scrape.py  # RuntimeError: GraphQL failed after 6 retries: ...ProxyError...\n\n# after\n$ unset HTTP_PROXY HTTPS_PROXY  # or fix proxy to allow api.github.com\n$ python scrape.py","handlingStrategy":"retry","validationCode":"import socket\n\ndef github_api_reachable(timeout: float = 5.0) -> bool:\n    try:\n        socket.create_connection((\"api.github.com\", 443), timeout=timeout).close()\n        return True\n    except OSError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    data = client.graphql(query)\nexcept RuntimeError as e:\n    if \"GraphQL failed after\" in str(e):\n        # transient transport failure: back off and restart the job (cache resumes)\n        time.sleep(300)\n        restart_job()\n    else:\n        raise","preventionTips":["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."],"tags":["github","graphql","network","retry","timeout"],"backgroundTag":null,"analyzedSha":"203007d19051dcd2ae33876786d117c99f6b0368","analyzedAt":"2026-08-15T02:48:39.846Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}