666ghj/MiroFish · error · FetchError

GitHub API returned an invalid stargazers_count

Error message

GitHub API returned an invalid stargazers_count

What it means

Final contract check on the payload: document['stargazers_count'] must be an int (strictly — type(count) is not int rejects bool, float, and numeric strings) and >= 0. The strictness is deliberate: JSON true is an int subclass in Python, and float counts would indicate a tampered or non-GitHub response.

Source

Thrown at scripts/fetch_star_count.py:122

                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
    if arguments:
        print("error: this command accepts no arguments", file=sys.stderr)
        return 2

    try:
        count = fetch_star_count(os.environ.get("GITHUB_TOKEN", ""))
    except FetchError as exc:
        print(f"error: {exc}", file=sys.stderr)
        return 1
    except Exception:
        print("error: unexpected internal failure", file=sys.stderr)
        return 1

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Check the exact field: curl the API and verify the key is stargazers_count (snake_case) in the returned object.
  2. If integrating a non-GitHub-compatible endpoint, map its field and coerce types before calling, or adapt the script; do not loosen the strict int check for real GitHub responses.
  3. Fix test doubles to return {'stargazers_count': 42} with a true JSON number.

Example fix

# before (test fixture)
body = json.dumps({"stargazersCount": 42.0})  # wrong key, float

# after
body = json.dumps({"stargazers_count": 42})
Defensive patterns

Strategy: validation

Validate before calling

import json, urllib.request

# pre-validate against a fetched document before relying on the strict parser
with urllib.request.urlopen("https://api.github.com/repos/666ghj/MiroFish") as r:
    doc = json.load(r)
value = doc.get("stargazers_count")
assert type(value) is int and value >= 0, f"unexpected count field: {value!r}"

Type guard

def is_valid_star_count(value: object) -> bool:
    """Strict int (bool rejected), non-negative."""
    return type(value) is int and value >= 0

Try / catch

try:
    count = fetch_star_count(token)
except FetchError as exc:
    if exc.args[0] == "GitHub API returned an invalid stargazers_count":
        raise SystemExit(
            "field missing/wrong type; real GitHub always returns int "
            "stargazers_count — inspect the raw payload"
        )
    raise

Prevention

When it happens

Trigger: A JSON proxy serializing counts as strings ('12345') or floats; a mock payload omitting stargazers_count (None) or using stargazersCount (camelCase, wrong field name); a boolean sneaking in via a lossy JSON re-encoder.

Common situations: Test fixtures with the wrong key or type; third-party GitHub-compatible APIs (Enterprise Server mirrors, api caches) that serialize differently; response-shape drift after a GitHub API version change (X-GitHub-Api-Version header pinned to API_VERSION).

Related errors


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