666ghj/MiroFish · error · FetchError

GitHub API response could not be read

Error message

GitHub API response could not be read

What it means

Raised when reading the response body (inside the with response block) raises TimeoutError or OSError — i.e. the connection was established and status received, but the body read failed or exceeded the 20-second timeout. Distinct from error 105: the request itself succeeded; streaming the payload back did not.

Source

Thrown at scripts/fetch_star_count.py:109

        exc.close()
        raise _status_error(status) from None
    except (urllib.error.URLError, TimeoutError, OSError):
        raise FetchError("GitHub API network request failed") from None
    except Exception:
        raise FetchError("GitHub API request could not be started") from None

    try:
        with response:
            if response.geturl() != API_URL:
                raise FetchError("GitHub API redirect was refused")
            status = response.getcode()
            if status != 200:
                raise _status_error(status)
            payload = _read_response(response)
    except FetchError:
        raise
    except (TimeoutError, OSError):
        raise FetchError("GitHub API response could not be read") from None
    except Exception:
        raise FetchError("GitHub API response could not be processed") from None

    try:
        document = json.loads(payload)
    except (UnicodeDecodeError, json.JSONDecodeError, ValueError):
        raise FetchError("GitHub API returned malformed JSON") from None
    if not isinstance(document, dict):
        raise FetchError("GitHub API response had an unexpected shape")

    count = document.get("stargazers_count")
    if type(count) is not int or count < 0:
        raise FetchError("GitHub API returned an invalid stargazers_count")
    return count


def main(argv: list[str] | None = None) -> int:
    arguments = sys.argv[1:] if argv is None else argv

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Retry with backoff — mid-body connection drops are overwhelmingly transient.
  2. If persistent, measure with curl --limit-rate or a raw socket read to identify where the transfer stalls; suspect proxy idle timeouts between the runner and api.github.com.
  3. For chronically slow networks, raise TIMEOUT_SECONDS (it covers both connect and read via client.open).
Defensive patterns

Strategy: retry

Try / catch

for attempt in range(3):
    try:
        count = fetch_star_count(token)
        break
    except FetchError as exc:
        if exc.args[0] != "GitHub API response could not be read":
            raise
        time.sleep(2 ** attempt)  # mid-body drops are transient
else:
    raise SystemExit("response body unreadable after retries")

Prevention

When it happens

Trigger: Server or middlebox closes the connection mid-body (Connection reset by peer); the read exceeds TIMEOUT_SECONDS=20 on a stalled connection; TLS renegotiation aborting the stream.

Common situations: Flaky CI networks where headers arrive but the body stalls; proxies with short idle timeouts that cut slow transfers; GitHub API incidents dropping connections.

Related errors


AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14). Data as JSON: /api/errors/436898eef2c12186. Report an issue: GitHub.