{"record":{"id":"2cc4c66f353bc87f","repo":"gastownhall/beads","slug":"graphql-errors-s","errorCode":null,"errorMessage":"GraphQL errors: %s","messagePattern":"GraphQL errors: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/linear/client.go","lineNumber":430,"sourceCode":"\n\t\tif resp.StatusCode < 200 || resp.StatusCode >= 300 {\n\t\t\treturn nil, lastStatus, fmt.Errorf(\"API error: %s (status %d)\", string(respBody), resp.StatusCode)\n\t\t}\n\n\t\tvar gqlResp struct {\n\t\t\tData   json.RawMessage `json:\"data\"`\n\t\t\tErrors []GraphQLError  `json:\"errors,omitempty\"`\n\t\t}\n\t\tif err := json.Unmarshal(respBody, &gqlResp); err != nil {\n\t\t\treturn nil, lastStatus, fmt.Errorf(\"failed to parse response: %w (body: %s)\", err, string(respBody))\n\t\t}\n\n\t\tif len(gqlResp.Errors) > 0 {\n\t\t\terrMsgs := make([]string, len(gqlResp.Errors))\n\t\t\tfor i, e := range gqlResp.Errors {\n\t\t\t\terrMsgs[i] = e.Message\n\t\t\t}\n\t\t\treturn nil, lastStatus, fmt.Errorf(\"GraphQL errors: %s\", strings.Join(errMsgs, \"; \"))\n\t\t}\n\n\t\treturn gqlResp.Data, lastStatus, nil\n\t}\n\n\treturn nil, lastStatus, fmt.Errorf(\"max retries (%d) exceeded: %w\", MaxRetries+1, lastErr)\n}\n\n// FetchIssues retrieves issues from Linear with optional filtering by state.\n// state can be: \"open\" (unstarted/started), \"closed\" (completed/canceled), or \"all\".\n// If ProjectID is set on the client, only issues from that project are returned.\nfunc (c *Client) FetchIssues(ctx context.Context, state string) ([]Issue, error) {\n\tvar allIssues []Issue\n\tvar cursor string\n\n\tfilter := map[string]interface{}{\n\t\t\"team\": map[string]interface{}{\n\t\t\t\"id\": map[string]interface{}{","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/linear/client.go#L412-L448","documentation":"Linear returned a well-formed GraphQL envelope whose errors array is non-empty (internal/linear/client.go:430): the transport and JSON layers succeeded but GraphQL itself rejected the query or mutation. The client joins all error messages with ';' and returns 'GraphQL errors: ...' with the last HTTP status. Not retried.","triggerScenarios":"GraphQL validation failures: unknown field/argument names (schema drift after Linear API changes), invalid UUIDs for team/project/issue IDs, missing required variables, or permission errors on resources the API key cannot see. Any Execute() with an invalid query shape produces this.","commonSituations":"Hand-written GraphQL queries with typos, queries written against an older Linear schema that has since changed, passing empty-string or malformed team/project IDs from config, or querying teams the API key is not a member of.","solutions":["Read the joined error messages — GraphQL names the exact invalid field, argument, or ID","Validate the query against the current Linear GraphQL schema (introspection or their schema docs)","Check configured team/project ID values are valid Linear UUIDs, not names or slugs","Verify the API key has access to the requested team/project","If a field disappeared after a Linear API change, update the query to the renamed field"],"exampleFix":"// before: filtering by team name instead of UUID, unsupported by the schema\nquery := `{ issues(filter: { team: { name: { eq: \"Eng\" } } }) { nodes { id } } }`\n_, err := client.Execute(ctx, &linear.GraphQLRequest{Query: query}) // GraphQL errors: ... 'name' ...\n// after: use the team id filter\nquery := `query($team: String!) { issues(filter: { team: { id: { eq: $team } } }) { nodes { id } } }`\n_, err = client.Execute(ctx, &linear.GraphQLRequest{Query: query, Variables: map[string]interface{}{\"team\": teamUUID}})","handlingStrategy":"type-guard","validationCode":"func validateIDs(teamID, projectID string) error {\n    for name, id := range map[string]string{\"team\": teamID, \"project\": projectID} {\n        if id == \"\" { continue }\n        if _, err := uuid.Parse(id); err != nil {\n            return fmt.Errorf(\"%s id %q is not a valid UUID\", name, id)\n        }\n    }\n    return nil\n}","typeGuard":"type GraphQLErrors []struct{ Message string }\nfunc asGraphQLErrors(err error) (msgs []string, ok bool) {\n    if !strings.HasPrefix(err.Error(), \"GraphQL errors: \") { return nil, false }\n    return strings.Split(strings.TrimPrefix(err.Error(), \"GraphQL errors: \"), \"; \"), true\n}","tryCatchPattern":"_, err := client.Execute(ctx, req)\nif err != nil {\n    if msgs, ok := asGraphQLErrors(err); ok {\n        return fmt.Errorf(\"linear rejected the query: %v — validate fields/IDs against the current schema\", msgs)\n    }\n    return err\n}","preventionTips":["Validate query fields against the current Linear GraphQL schema; pin/review after API changes","Store team/project references as Linear UUIDs, never names or slugs","Verify the API key can access the requested team/project before batch runs","Test new queries with a minimal single-item request before running them at scale"],"tags":["graphql","schema","validation","linear-client"],"backgroundTag":"graphql-errors","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}