zed-industries/zed · error · RuntimeError
GraphQL error: {result['errors']}
Error message
GraphQL error: {result['errors']} What it means
The triage queue board's github_graphql retries only HTTP statuses in RETRYABLE_STATUS_CODES (fixed sleep, 30s timeout); a 200 response carrying an "errors" array raises this RuntimeError with the raw errors. GraphQL application failures — the ones that come back with HTTP 200 — are therefore never retried.
Source
Thrown at script/github-triage-queue-board.py:56
def github_graphql(query, variables):
for attempt in range(MAX_RETRIES + 1):
response = requests.post(
f"{GITHUB_API_URL}/graphql",
headers=GITHUB_HEADERS,
json={"query": query, "variables": variables},
timeout=30,
)
if response.status_code in RETRYABLE_STATUS_CODES and attempt < MAX_RETRIES:
print(
f"GitHub API returned {response.status_code}, retrying in {RETRY_DELAY_SECONDS}s (attempt {attempt + 1}/{MAX_RETRIES})..."
)
time.sleep(RETRY_DELAY_SECONDS)
continue
response.raise_for_status()
result = response.json()
if "errors" in result:
raise RuntimeError(f"GraphQL error: {result['errors']}")
return result["data"]
raise RuntimeError("github_graphql: retry loop exited without return")
def github_rest_get(path):
for attempt in range(MAX_RETRIES + 1):
response = requests.get(
f"{GITHUB_API_URL}/{path}", headers=GITHUB_HEADERS, timeout=30
)
if response.status_code in RETRYABLE_STATUS_CODES and attempt < MAX_RETRIES:
print(
f"GitHub API returned {response.status_code}, retrying in {RETRY_DELAY_SECONDS}s (attempt {attempt + 1}/{MAX_RETRIES})..."
)
time.sleep(RETRY_DELAY_SECONDS)
continue
response.raise_for_status()
return response.json()
raise RuntimeError("github_rest_get: retry loop exited without return")View on GitHub (pinned to bc538def45)
Solutions
- Read the errors array in the message to find the failing field/id/permission
- Refresh the token and confirm project scopes
- Re-run the query standalone with the same variables to reproduce
- Make body-level rate-limit errors retryable like the HTTP 429 branch
Example fix
// before
result = response.json()
if "errors" in result:
raise RuntimeError(f"GraphQL error: {result['errors']}")
// after
result = response.json()
if "errors" in result:
rate_limited = any("rate limit" in str(e.get("message", "")).lower() for e in result["errors"])
if rate_limited and attempt < MAX_RETRIES:
time.sleep(RETRY_DELAY_SECONDS)
continue
raise RuntimeError(f"GraphQL error: {result['errors']}") Defensive patterns
Strategy: retry
Validate before calling
def graphql_request_is_well_formed(query: str, variables: dict) -> bool:
return bool(query.strip()) and isinstance(variables, dict) Type guard
def is_graphql_error_body(payload: dict) -> bool:
return isinstance(payload, dict) and bool(payload.get("errors")) Try / catch
try:
data = github_graphql(query, variables)
except RuntimeError as exc:
if "rate limit" in str(exc).lower():
time.sleep(RETRY_DELAY_SECONDS)
data = github_graphql(query, variables)
else:
raise Prevention
- Re-resolve ids each run instead of caching node ids
- Keep the CI token's project scopes correct after rotations
- Smoke-test queries after GitHub schema announcements
- Separate retryable from permanent GraphQL errors in handling
When it happens
Trigger: Board queries return 200 + errors: stale project/item node ids, missing read:project on the token, deprecated fields in the query after schema changes, or rate-limit text embedded in the errors body.
Common situations: Expired CI token; project recreated so fetch_project_id/item ids go stale; GitHub schema evolution breaking a fragment; rate pressure from overlapping scheduled runs.
Related errors
- GraphQL errors: {json.dumps(data['errors'])[:300]}
- 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/03f156bffdde1bf4.
Report an issue: GitHub.