{"record":{"id":"f429a219c4822f28","repo":"666ghj/MiroFish","slug":"github-api-network-request-failed","errorCode":null,"errorMessage":"GitHub API network request failed","messagePattern":"GitHub API network request failed","errorType":"exception","errorClass":"FetchError","httpStatus":null,"severity":"error","filePath":"scripts/fetch_star_count.py","lineNumber":94,"sourceCode":"    request = urllib.request.Request(\n        API_URL,\n        headers={\n            \"Accept\": \"application/vnd.github+json\",\n            \"Authorization\": f\"Bearer {token}\",\n            \"User-Agent\": \"Repository-Star-History-Fetcher\",\n            \"X-GitHub-Api-Version\": API_VERSION,\n        },\n        method=\"GET\",\n    )\n    client = opener or _build_opener()\n    try:\n        response = client.open(request, timeout=TIMEOUT_SECONDS)\n    except urllib.error.HTTPError as exc:\n        status = exc.code\n        exc.close()\n        raise _status_error(status) from None\n    except (urllib.error.URLError, TimeoutError, OSError):\n        raise FetchError(\"GitHub API network request failed\") from None\n    except Exception:\n        raise FetchError(\"GitHub API request could not be started\") from None\n\n    try:\n        with response:\n            if response.geturl() != API_URL:\n                raise FetchError(\"GitHub API redirect was refused\")\n            status = response.getcode()\n            if status != 200:\n                raise _status_error(status)\n            payload = _read_response(response)\n    except FetchError:\n        raise\n    except (TimeoutError, OSError):\n        raise FetchError(\"GitHub API response could not be read\") from None\n    except Exception:\n        raise FetchError(\"GitHub API response could not be processed\") from None\n","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/scripts/fetch_star_count.py#L76-L112","documentation":"Raised when client.open(request, timeout=20) fails with URLError, TimeoutError, or OSError while establishing/sending the request. This bucket covers every transport-level failure before any HTTP response exists: DNS failure, connection refused, TLS errors, and the 20-second connect/read timeout expiring.","triggerScenarios":"No network egress (CI runner offline, firewall blocking api.github.com:443); DNS resolution failure; TLS handshake rejected by a filtering middlebox; request exceeding TIMEOUT_SECONDS=20 on a slow link.","commonSituations":"Self-hosted runners without internet; corporate firewalls requiring a proxy that urllib ignores (HTTPS_PROXY not honored by the custom opener); DNS outages; GitHub API connectivity blips.","solutions":["Test reachability from the same host: curl -v --max-time 20 https://api.github.com/ (expect 200 or a rate-limit body).","If a proxy is required, ensure HTTPS_PROXY is set and reachable; note the script builds its own opener, so proxy env handling comes from urllib's defaults.","Retry after a short backoff — transient DNS/TLS failures are the most common cause and self-heal.","For frequent CI flakes, schedule the workflow with retry logic (workflow_run re-run, or a wrapper that retries on this specific message)."],"exampleFix":"# before\ntry:\n    count = fetch_star_count(os.environ[\"GITHUB_TOKEN\"])\nexcept FetchError as exc:\n    sys.exit(f\"error: {exc}\")\n\n# after: bounded retry for transport-level failures only\nfor attempt in range(3):\n    try:\n        count = fetch_star_count(os.environ[\"GITHUB_TOKEN\"])\n        break\n    except FetchError as exc:\n        if exc.args[0] != \"GitHub API network request failed\" or attempt == 2:\n            raise\n        time.sleep(2 ** attempt)","handlingStrategy":"retry","validationCode":"import socket\n\n# cheap pre-flight: DNS + TCP reachability before the real call\ntry:\n    socket.create_connection((\"api.github.com\", 443), timeout=5).close()\nexcept OSError as exc:\n    raise SystemExit(f\"no egress to api.github.com: {exc}\") from None","typeGuard":null,"tryCatchPattern":"last: Exception | None = None\nfor attempt in range(3):\n    try:\n        count = fetch_star_count(token)\n        break\n    except FetchError as exc:\n        if exc.args[0] != \"GitHub API network request failed\":\n            raise\n        last, delay = exc, 2 ** attempt\n        time.sleep(delay)\nelse:\n    raise SystemExit(f\"github unreachable after retries: {last}\")","preventionTips":["Verify egress (DNS + TCP 443) from the runner before relying on scheduled fetches.","Honor proxy requirements: ensure HTTPS_PROXY reaches the process if the network demands it.","Retry only transport-level failures with exponential backoff; do not retry 4xx responses."],"tags":["network","timeout","dns","firewall","fetch-star-count"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}