{"record":{"id":"535388e452fc0000","repo":"666ghj/MiroFish","slug":"github-graphql-returned-an-invalid-star-timestamp","errorCode":null,"errorMessage":"GitHub GraphQL returned an invalid star timestamp","messagePattern":"GitHub GraphQL returned an invalid star timestamp","errorType":"exception","errorClass":"StarHistoryError","httpStatus":null,"severity":"error","filePath":"scripts/star_history.py","lineNumber":280,"sourceCode":"        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):\n            raise StarHistoryError(\"GitHub GraphQL returned an invalid page cursor\")\n        if has_next_page and not end_cursor:\n            raise StarHistoryError(\"GitHub GraphQL omitted the next page cursor\")\n\n        return StargazerPage(\n            total_count=total_count,\n            edges=tuple(edges),\n            has_next_page=has_next_page,\n            end_cursor=end_cursor,\n            rate_remaining=rate_remaining,\n        )","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/scripts/star_history.py#L262-L298","documentation":"An edge's starredAt field was not a string. starredAt is required to place each star on the history timeline, so a non-string value (null, number, object) raises StarHistoryError('GitHub GraphQL returned an invalid star timestamp') before _parse_github_timestamp is attempted (that function only accepts str).","triggerScenarios":"Edge with starredAt: null (field not selected in the query, or edge for an invisible user), or a fixture where starredAt was replaced by an epoch number.","commonSituations":"Query edited to drop the starredAt selection; hand-written fixtures; GitHub schema change renaming the field (e.g. to starred_at).","solutions":["Ensure the query selects starredAt on every edge","Fix fixtures to use ISO 8601 strings like '2024-01-15T10:30:00Z'","Log the edge to confirm which value type arrived"],"exampleFix":"// before\nedges { cursor }\n\n// after\nedges { cursor starredAt }","handlingStrategy":"validation","validationCode":"if not all(isinstance(e.get(\"starredAt\"), str) for e in raw_edges if isinstance(e, dict)):\n    raise StarHistoryError(\"edges missing starredAt; query must select starredAt\")","typeGuard":"def edge_has_starred_at(edge: object) -> TypeGuard[dict]:\n    return isinstance(edge, dict) and isinstance(edge.get(\"starredAt\"), str)","tryCatchPattern":"try:\n    page = _parse_graphql_page(payload)\nexcept StarHistoryError as exc:\n    if \"invalid star timestamp\" in str(exc) and \"type\" not in str(exc):\n        raise StarHistoryError(\"cannot place stars on timeline without starredAt\") from exc\n    raise","preventionTips":["Keep `starredAt` in the query selection; it is required for the history timeline","Validate fixture edges with the same guard as production code so tests catch missing fields"],"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"}