zed-industries/zed · error · ValueError
GraphQL errors: {json.dumps(data['errors'])[:300]}
Error message
GraphQL errors: {json.dumps(data['errors'])[:300]} What it means
Raised when the GitHub GraphQL endpoint answers HTTP 200 but the response body contains an "errors" array; GitHub reports query-level failures (unresolvable ids, bad variables, missing scopes, rate-limit messages) in a 200 body, not as HTTP errors. The wrapper converts that into a ValueError carrying the first 300 characters of the serialized errors. Because the surrounding except only catches requests.RequestException, this ValueError escapes immediately and is never retried, even when the body error is transient.
Source
Thrown at script/github-check-new-issue-for-duplicates.py:104
"""Search issues, using GitHub's relevance ordering unless a sort is specified."""
params = {"q": query, "per_page": per_page}
if sort:
params.update({"sort": sort, "order": "desc"})
return github_api_get("/search/issues", params).get("items", [])
def github_api_graphql(query, variables=None):
"""Run a GraphQL query against the GitHub API, retrying transient failures. """
url = f"{GITHUB_API}/graphql"
for attempt in range(3):
try:
response = requests.post(
url, headers=GITHUB_HEADERS, json={"query": query, "variables": variables or {}}
)
response.raise_for_status()
data = response.json()
if "errors" in data:
raise ValueError(f"GraphQL errors: {json.dumps(data['errors'])[:300]}")
return data["data"]
except requests.RequestException as e:
transient = isinstance(e, (requests.ConnectionError, requests.Timeout)) or (
isinstance(e, requests.HTTPError) and e.response.status_code in TRANSIENT_HTTP_STATUSES
)
if not transient or attempt == 2:
raise
wait = 2 ** attempt
log(f" Transient GitHub GraphQL error ({e}); retrying in {wait}s")
time.sleep(wait)
def check_team_membership(org, team_slug, username):
"""Check if user is an active member of a team."""
try:
data = github_api_get(f"/orgs/{org}/teams/{team_slug}/memberships/{username}")
return data.get("state") == "active"
except requests.HTTPError as e:View on GitHub (pinned to bc538def45)
Solutions
- Log the full errors array (data['errors'][0]['message'] and ['type']) instead of the 300-char slice, then fix the exact query/variable/id it names
- Check the token: expiry date and scopes (repo, read:project) against the data being queried
- Reproduce with curl -H "Authorization: bearer $TOKEN" -d '{"query":"..."}' https://api.github.com/graphql to isolate the failing field
- If the error message indicates a rate limit, sleep and retry inside the loop instead of letting the ValueError escape (it currently bypasses the retry logic)
Example fix
// before
if "errors" in data:
raise ValueError(f"GraphQL errors: {json.dumps(data['errors'])[:300]}")
// after
if "errors" in data:
message = str(data['errors'][0].get('message', ''))
if 'rate limit' in message.lower() and attempt < 2:
wait = 2 ** attempt
log(f" Transient GraphQL body error; retrying in {wait}s")
time.sleep(wait)
continue
raise ValueError(f"GraphQL errors: {json.dumps(data['errors'])[:300]}") Defensive patterns
Strategy: retry
Validate before calling
def graphql_request_is_well_formed(query: str, variables: dict | None) -> bool:
return bool(query and query.strip()) and (variables is None or isinstance(variables, dict)) Type guard
def is_graphql_error_body(payload: dict) -> bool:
return isinstance(payload, dict) and isinstance(payload.get("errors"), list) and len(payload["errors"]) > 0 Try / catch
try:
data = github_api_graphql(query, variables)
except ValueError as exc:
# ValueError escapes the wrapper's RequestException handler, so classify here
text = str(exc)
if "rate limit" in text.lower():
time.sleep(5)
data = github_api_graphql(query, variables)
else:
raise Prevention
- Check the rate limit with a cheap query before batch jobs
- Validate node ids and issue numbers before embedding them in queries
- Keep the token scoped but sufficient: repo and read:project
- Log the full errors array rather than a 300-char slice
When it happens
Trigger: POST to {GITHUB_API}/graphql returns 200 with errors, e.g. "Could not resolve to an Issue with the number of X" for a wrong/deleted issue number, INSUFFICIENT_SCOPES when GITHUB_TOKEN lacks repo/read:project, a malformed query or wrong variable type after a GitHub schema change, or a secondary rate-limit message embedded in the errors body.
Common situations: Expired or under-scoped CI token; querying an issue that was deleted or lives in another repo; GitHub GraphQL schema renames breaking a stored query; heavy CI runs hitting secondary rate limits that surface in the 200 body.
Related errors
- GraphQL error: {result['errors']}
- GraphQL error: {result['errors']}
- GraphQL error: {result['errors']}
- GraphQL failed after {retries} retries: {last_err}
- GraphQL errors: {data['errors']}
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/187e8f3c10dc059f.
Report an issue: GitHub.