666ghj/MiroFish · error · StarHistoryError
GitHub GraphQL returned an invalid edge cursor
Error message
GitHub GraphQL returned an invalid edge cursor
What it means
An edge object lacked a usable cursor: cursor was not a str, or was an empty string. Cursors are mandatory for cursor-based pagination of stargazers (they are passed as the $after variable for the next page), so the parser raises StarHistoryError('GitHub GraphQL returned an invalid edge cursor') rather than attempting to continue from a missing position.
Source
Thrown at scripts/star_history.py:278
raise StarHistoryError("GitHub GraphQL response had an unexpected shape")
total_count = _strict_non_negative_int(
stargazers.get("totalCount"), "GraphQL totalCount"
)
rate_remaining = _strict_non_negative_int(
rate_limit.get("remaining"), "GraphQL rate remaining"
)
if not isinstance(raw_edges, list):
raise StarHistoryError("GitHub GraphQL edges were not a list")
edges: list[StargazerEdge] = []
for raw_edge in raw_edges:
if not isinstance(raw_edge, dict):
raise StarHistoryError("GitHub GraphQL returned an invalid edge")
cursor = raw_edge.get("cursor")
starred_at = raw_edge.get("starredAt")
if not isinstance(cursor, str) or not cursor:
raise StarHistoryError("GitHub GraphQL returned an invalid edge cursor")
if not isinstance(starred_at, str):
raise StarHistoryError("GitHub GraphQL returned an invalid star timestamp")
edges.append(StargazerEdge(cursor, _parse_github_timestamp(starred_at)))
has_next_page = page_info.get("hasNextPage")
end_cursor = page_info.get("endCursor")
if type(has_next_page) is not bool:
raise StarHistoryError("GitHub GraphQL returned invalid page information")
if end_cursor is not None and not isinstance(end_cursor, str):
raise StarHistoryError("GitHub GraphQL returned an invalid page cursor")
if has_next_page and not end_cursor:
raise StarHistoryError("GitHub GraphQL omitted the next page cursor")
return StargazerPage(
total_count=total_count,
edges=tuple(edges),
has_next_page=has_next_page,
end_cursor=end_cursor,View on GitHub (pinned to b5b53acc57)
Solutions
- Restore `cursor` in the edges selection of the GraphQL query if it was removed
- Fix test fixtures so every edge has a non-empty string cursor
- Log the failing edge to distinguish null vs empty string — null means the field was not selected, empty means malformed data
Example fix
// before (query fragment)
edges { node { ... } }
// after (query fragment)
edges { cursor starredAt } Defensive patterns
Strategy: validation
Validate before calling
for edge in raw_edges:
if not isinstance(edge, dict) or not isinstance(edge.get("cursor"), str) or not edge["cursor"]:
raise StarHistoryError("edge without usable cursor; cannot paginate safely")
break Type guard
def has_usable_cursor(edge: object) -> TypeGuard[dict]:
return isinstance(edge, dict) and isinstance(edge.get("cursor"), str) and bool(edge["cursor"]) Try / catch
try:
page = _parse_graphql_page(payload)
except StarHistoryError as exc:
if "invalid edge cursor" in str(exc):
raise StarHistoryError("pagination aborted: GitHub omitted a cursor — restart collection from last good cursor") from exc
raise Prevention
- Always select `cursor` in the edges block of the GraphQL query
- Persist the last good cursor so an aborted pagination run can resume instead of restarting
When it happens
Trigger: An edge with cursor: null (cursor field not selected in the query, or GitHub omitted it), cursor: 123, or cursor: "". Also happens if the query was edited to drop the cursor selection while the parser still expects it.
Common situations: Hand-modified GraphQL query that removed `cursor` from the edges selection; test fixtures copying edges without cursors; GitHub API behavior change.
Related errors
- GitHub GraphQL returned invalid page information
- GitHub GraphQL returned an invalid page cursor
- GitHub GraphQL omitted the next page cursor
- GitHub returned an invalid pagination cursor
- GitHub GraphQL edges were not a list
AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14).
Data as JSON: /api/errors/9684808b97f7280c.
Report an issue: GitHub.