{"record":{"id":"68c5f4e5d132e2e0","repo":"gastownhall/beads","slug":"graphql-error-s","errorCode":null,"errorMessage":"GraphQL error: %s","messagePattern":"GraphQL error: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/gitlab/client.go","lineNumber":524,"sourceCode":"\n\t// GraphQL endpoint is at /api/graphql (not under /api/v4/)\n\turlStr := c.BaseURL + \"/api/graphql\"\n\trespBody, _, err := c.doRequest(ctx, http.MethodPost, urlStr, body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"GraphQL request failed: %w\", err)\n\t}\n\n\tvar result struct {\n\t\tData   json.RawMessage `json:\"data\"`\n\t\tErrors []struct {\n\t\t\tMessage string `json:\"message\"`\n\t\t} `json:\"errors\"`\n\t}\n\tif err := json.Unmarshal(respBody, &result); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse GraphQL response: %w\", err)\n\t}\n\tif len(result.Errors) > 0 {\n\t\treturn nil, fmt.Errorf(\"GraphQL error: %s\", result.Errors[0].Message)\n\t}\n\treturn result.Data, nil\n}\n\n// WorkItem represents a GitLab work item from the GraphQL API.\ntype WorkItem struct {\n\tID    string `json:\"id\"`  // Global ID (gid://gitlab/WorkItem/123)\n\tIID   string `json:\"iid\"` // Project-scoped ID\n\tTitle string `json:\"title\"`\n\tType  string `json:\"type\"` // Work item type name\n}\n\n// defaultTaskTypeID is the fallback GID for older GitLab instances where the\n// workItemTypes GraphQL query is unavailable.\nconst defaultTaskTypeID = \"gid://gitlab/WorkItems::Type/5\"\n\n// getTaskWorkItemTypeID returns the GraphQL GID for the \"Task\" work item type.\n// It queries the GitLab instance once per session and caches the result.","sourceCodeStart":506,"sourceCodeEnd":542,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/gitlab/client.go#L506-L542","documentation":"The GraphQL endpoint returned a valid response envelope whose errors array is non-empty, meaning GitLab rejected the query at the GraphQL level. Only the first error's message is surfaced. This is a semantic/authorization/query error, not a transport error — the request reached the server and was evaluated.","triggerScenarios":"Calls to getTaskWorkItemTypeID, CreateTaskWorkItem, or GetWorkItemGID where the query is invalid (unknown field, e.g. workItem types not enabled), the token lacks permission, or the referenced resource does not exist.","commonSituations":"Using a personal access token without api scope; querying workItems on a GitLab version where the field doesn't exist (pre-16.x); referencing a project/group ID the token cannot read; typos in GraphQL query fields after an API upgrade.","solutions":["Read the surfaced GraphQL error message — it names the exact problem (field, permission, or resource).","Verify the token's scopes (api/api_scope) and target project permissions.","Check the GitLab version supports the queried GraphQL schema fields (work items require recent versions).","Log all result.Errors, not just [0], when multiple errors are returned."],"exampleFix":"// before: only first error shown\nreturn nil, fmt.Errorf(\"GraphQL error: %s\", result.Errors[0].Message)\n// after: collect all messages\nmsgs := make([]string, 0, len(result.Errors))\nfor _, e := range result.Errors {\n    msgs = append(msgs, e.Message)\n}\nreturn nil, fmt.Errorf(\"GraphQL error: %s\", strings.Join(msgs, \"; \"))","handlingStrategy":"try-catch","validationCode":"// validate token scope and project access before GraphQL calls\nresp, err := http.Get(client.BaseURL + \"/api/v4/user\" + \"?private_token=\" + token)\n// expect 200; 401/403 means the token will fail GraphQL permissions too","typeGuard":null,"tryCatchPattern":"data, err := client.CreateTaskWorkItem(ctx, req)\nif err != nil {\n    var gqlErr *GitLabGraphQLError\n    if errors.As(err, &gqlErr) || strings.Contains(err.Error(), \"GraphQL error:\") {\n        // surface gqlErr message to caller; it names the permission/schema problem\n    }\n    return err\n}","preventionTips":["Use tokens with the api scope and Developer+ role on target projects.","Keep GitLab server and client schema expectations in sync (test against the target version).","Validate project paths and IDs exist before mutation calls."],"tags":["gitlab","graphql","api-error","permissions"],"backgroundTag":"graphql-errors-response","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}