666ghj/MiroFish · error · FetchError

GitHub API request could not be started

Error message

GitHub API request could not be started

What it means

The catch-all for any exception from client.open that is not HTTPError, URLError, TimeoutError, or OSError — for example ValueError from a malformed request object, TypeError from a bad opener, or an unexpected exception type leaking from a custom opener passed via the opener parameter. It marks failures to even start the request, as opposed to network failures mid-flight.

Source

Thrown at scripts/fetch_star_count.py:96

        headers={
            "Accept": "application/vnd.github+json",
            "Authorization": f"Bearer {token}",
            "User-Agent": "Repository-Star-History-Fetcher",
            "X-GitHub-Api-Version": API_VERSION,
        },
        method="GET",
    )
    client = opener or _build_opener()
    try:
        response = client.open(request, timeout=TIMEOUT_SECONDS)
    except urllib.error.HTTPError as exc:
        status = exc.code
        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)

View on GitHub (pinned to b5b53acc57)

Solutions

  1. If passing a custom opener, make its failure modes raise urllib.error.URLError or OSError so they map to the more precise 'network request failed' error.
  2. Inspect the chained exception (raise ... from None discards it in this branch — reproduce without the wrapper to see the original traceback).
  3. In tests, assert against this message when deliberately raising unexpected exceptions, or fix the double to raise standard library errors.
Defensive patterns

Strategy: try-catch

Validate before calling

import urllib.request

def is_usable_opener(opener: object) -> bool:
    """An opener must expose OpenerDirector.open before we rely on it."""
    return callable(getattr(opener, "open", None))

Try / catch

try:
    count = fetch_star_count(token, opener=my_opener)
except FetchError as exc:
    if exc.args[0] == "GitHub API request could not be started":
        # the custom opener raised an unexpected exception type;
        # run the opener directly once to capture the real traceback
        raise

Prevention

When it happens

Trigger: Calling fetch_star_count(token, opener=my_opener) with an opener whose .open raises an arbitrary exception (not OSError-derived); a Request object invalidated by exotic header handling; programming errors in custom openers used for testing.

Common situations: Test doubles that raise pytest.fail or custom exceptions instead of OSError; monkeypatched urlopen raising RuntimeError; a custom opener that does not implement the OpenerDirector protocol.

Related errors


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