{"record":{"id":"0a0a79dd3ec377a1","repo":"666ghj/MiroFish","slug":"github-graphql-edges-were-not-a-list","errorCode":null,"errorMessage":"GitHub GraphQL edges were not a list","messagePattern":"GitHub GraphQL edges were not a list","errorType":"exception","errorClass":"StarHistoryError","httpStatus":null,"severity":"error","filePath":"scripts/star_history.py","lineNumber":269,"sourceCode":"            raw_edges = stargazers[\"edges\"]\n            page_info = stargazers[\"pageInfo\"]\n        except (KeyError, TypeError) as exc:\n            raise StarHistoryError(\"GitHub GraphQL response had an unexpected shape\") from exc\n\n        if not all(\n            isinstance(value, dict)\n            for value in (data, repository, stargazers, rate_limit, page_info)\n        ):\n            raise StarHistoryError(\"GitHub GraphQL response had an unexpected shape\")\n\n        total_count = _strict_non_negative_int(\n            stargazers.get(\"totalCount\"), \"GraphQL totalCount\"\n        )\n        rate_remaining = _strict_non_negative_int(\n            rate_limit.get(\"remaining\"), \"GraphQL rate remaining\"\n        )\n        if not isinstance(raw_edges, list):\n            raise StarHistoryError(\"GitHub GraphQL edges were not a list\")\n\n        edges: list[StargazerEdge] = []\n        for raw_edge in raw_edges:\n            if not isinstance(raw_edge, dict):\n                raise StarHistoryError(\"GitHub GraphQL returned an invalid edge\")\n            cursor = raw_edge.get(\"cursor\")\n            starred_at = raw_edge.get(\"starredAt\")\n            if not isinstance(cursor, str) or not cursor:\n                raise StarHistoryError(\"GitHub GraphQL returned an invalid edge cursor\")\n            if not isinstance(starred_at, str):\n                raise StarHistoryError(\"GitHub GraphQL returned an invalid star timestamp\")\n            edges.append(StargazerEdge(cursor, _parse_github_timestamp(starred_at)))\n\n        has_next_page = page_info.get(\"hasNextPage\")\n        end_cursor = page_info.get(\"endCursor\")\n        if type(has_next_page) is not bool:\n            raise StarHistoryError(\"GitHub GraphQL returned invalid page information\")\n        if end_cursor is not None and not isinstance(end_cursor, str):","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/scripts/star_history.py#L251-L287","documentation":"After the response envelope passed the dict-shape checks, data.repository.stargazers.edges was not a JSON array. The parser guards every node type strictly and refuses to iterate over a non-list, raising StarHistoryError('GitHub GraphQL edges were not a list'). It protects the subsequent per-edge loop from blowing up with a less clear TypeError.","triggerScenarios":"A GraphQL response where stargazers.edges is null (e.g. repository exists but stargazers connection returned null), an object keyed by cursor instead of a list, or a truncated/malformed payload from a proxy.","commonSituations":"GitHub returning stargazers: null for an inaccessible or empty connection; a modified GraphQL query that aliased or restructured edges; a mocked/stubbed API in tests returning a dict of edges.","solutions":["Log the raw stargazers sub-object when this fires to see whether edges is null or an object","If edges is null because the connection is unavailable, treat that as the same case as error 120 and check the top-level errors array / token scopes","Fix any local modification of the query string that dropped the edges [] selection"],"exampleFix":"// before\nraw_edges = stargazers[\"edges\"]\n\n// after\nraw_edges = stargazers.get(\"edges\") or []  # only if a null connection is expected; otherwise keep raising","handlingStrategy":"validation","validationCode":"edges = (payload[\"data\"][\"repository\"].get(\"stargazers\") or {}).get(\"edges\")\nif edges is None:\n    raise StarHistoryError(\"stargazers connection missing — check token scopes and repo visibility\")","typeGuard":"def has_edge_list(payload: dict) -> TypeGuard[dict]:\n    sg = payload.get(\"data\", {}).get(\"repository\", {}).get(\"stargazers\", {})\n    return isinstance(sg, dict) and isinstance(sg.get(\"edges\"), list)","tryCatchPattern":"try:\n    page = _parse_graphql_page(payload)\nexcept StarHistoryError as exc:\n    if \"edges were not a list\" in str(exc):\n        logger.warning(\"stargazers edges missing for repo; treating as empty page\")\n        page = StargazerPage(0, (), False, None, 0)\n    else:\n        raise","preventionTips":["Keep the edges [] selection in the GraphQL query in sync with the parser","Treat a null stargazers connection the same as an envelope error and surface the errors array"],"tags":["github-api","graphql","parsing","validation","star-history"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}