{"record":{"id":"02509757a16bc4fb","repo":"zed-industries/zed","slug":"graphql-error-result-errors-025097","errorCode":null,"errorMessage":"GraphQL error: {result['errors']}","messagePattern":"GraphQL error: (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"script/github-community-pr-board.py","lineNumber":280,"sourceCode":"\ndef github_graphql(query, variables):\n    \"\"\"Execute a GitHub GraphQL query. Retries on transient server errors.\"\"\"\n    for attempt in range(MAX_RETRIES + 1):\n        response = requests.post(\n            f\"{GITHUB_API_URL}/graphql\",\n            headers=GITHUB_HEADERS,\n            json={\"query\": query, \"variables\": variables},\n        )\n        if response.status_code in RETRYABLE_STATUS_CODES and attempt < MAX_RETRIES:\n            print(\n                f\"GitHub API returned {response.status_code}, retrying in {RETRY_DELAY_SECONDS}s (attempt {attempt + 1}/{MAX_RETRIES})...\"\n            )\n            time.sleep(RETRY_DELAY_SECONDS)\n            continue\n        response.raise_for_status()\n        result = response.json()\n        if \"errors\" in result:\n            raise RuntimeError(f\"GraphQL error: {result['errors']}\")\n        return result[\"data\"]\n    raise RuntimeError(\"github_graphql: retry loop exited without return\")\n\n\ndef github_rest_get(path):\n    \"\"\"GET from the GitHub REST API. Retries on transient server errors.\"\"\"\n    for attempt in range(MAX_RETRIES + 1):\n        response = requests.get(f\"{GITHUB_API_URL}/{path}\", headers=GITHUB_HEADERS)\n        if response.status_code in RETRYABLE_STATUS_CODES and attempt < MAX_RETRIES:\n            print(\n                f\"GitHub API returned {response.status_code}, retrying in {RETRY_DELAY_SECONDS}s (attempt {attempt + 1}/{MAX_RETRIES})...\"\n            )\n            time.sleep(RETRY_DELAY_SECONDS)\n            continue\n        response.raise_for_status()\n        return response.json()\n    raise RuntimeError(\"github_rest_get: retry loop exited without return\")\n","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/zed-industries/zed/blob/bc538def4545534201bbfcac4e95ac34ea6501b6/script/github-community-pr-board.py#L262-L298","documentation":"The github_graphql helper retries only HTTP-level transient statuses (RETRYABLE_STATUS_CODES with fixed delay); once a 200 arrives whose body contains an \"errors\" array it raises this RuntimeError immediately with the raw errors. GitHub GraphQL puts application failures (bad node ids, permission errors, schema problems) into a 200 body, so this error fires on query-level failures that retrying the HTTP call would not fix.","triggerScenarios":"POST to GITHUB_API_URL/graphql for the community PR board query returns 200 + errors: project/item node ids from another org, token without project read, a ProjectV2 field fragment referencing a field GitHub deprecated, or mutation variables with wrong GraphQL types.","commonSituations":"GITHUB_TOKEN expired between scheduled runs; project or items recreated so cached node ids are stale; GitHub deprecating or renaming a ProjectV2 field in the schema; running against a different owner/repo than the token permits.","solutions":["Read the errors array inside the message: the type and message fields name the exact failing field or id","Verify the token is valid and has read:project (plus write for the mutations in this script)","Re-run the exact query with the same variables in a GraphQL client to isolate the failing fragment","If the body errors are rate-limit messages, include them in the retry condition instead of raising on the first occurrence"],"exampleFix":"// before\nresult = response.json()\nif \"errors\" in result:\n    raise RuntimeError(f\"GraphQL error: {result['errors']}\")\nreturn result[\"data\"]\n\n// after\nresult = response.json()\nif \"errors\" in result:\n    rate_limited = any(\"rate limit\" in str(e.get(\"message\", \"\")).lower() for e in result[\"errors\"])\n    if rate_limited and attempt < MAX_RETRIES:\n        time.sleep(RETRY_DELAY_SECONDS)\n        continue\n    raise RuntimeError(f\"GraphQL error: {result['errors']}\")\nreturn result[\"data\"]","handlingStrategy":"retry","validationCode":"def token_can_read_projects() -> bool:\n    r = requests.get(f\"{GITHUB_API_URL}/user\", headers=GITHUB_HEADERS, timeout=30)\n    return r.status_code == 200","typeGuard":"def is_graphql_error_body(payload: dict) -> bool:\n    return isinstance(payload, dict) and bool(payload.get(\"errors\"))","tryCatchPattern":"try:\n    data = github_graphql(query, variables)\nexcept RuntimeError as exc:\n    if \"rate limit\" in str(exc).lower():\n        time.sleep(RETRY_DELAY_SECONDS)\n        data = github_graphql(query, variables)\n    else:\n        raise","preventionTips":["Keep node ids fresh: re-resolve project numbers each run instead of caching","Monitor token expiry in CI","Test queries against the GraphQL schema in a client before shipping","Distinguish retryable body errors (rate limit) from permanent ones in handling"],"tags":["github-api","graphql","python","rate-limit","api-auth"],"backgroundTag":null,"analyzedSha":"bc538def4545534201bbfcac4e95ac34ea6501b6","analyzedAt":"2026-08-16T07:30:46.435Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}