{"record":{"id":"929c6966860017fc","repo":"gastownhall/beads","slug":"work-item-creation-returned-nil","errorCode":null,"errorMessage":"work item creation returned nil","messagePattern":"work item creation returned nil","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/gitlab/client.go","lineNumber":630,"sourceCode":"\t\t\tWorkItem *struct {\n\t\t\t\tID     string `json:\"id\"`\n\t\t\t\tIID    string `json:\"iid\"`\n\t\t\t\tTitle  string `json:\"title\"`\n\t\t\t\tWebURL string `json:\"webUrl\"`\n\t\t\t\tType   struct {\n\t\t\t\t\tName string `json:\"name\"`\n\t\t\t\t} `json:\"workItemType\"`\n\t\t\t} `json:\"workItem\"`\n\t\t} `json:\"workItemCreate\"`\n\t}\n\tif err := json.Unmarshal(data, &resp); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse work item response: %w\", err)\n\t}\n\tif len(resp.WorkItemCreate.Errors) > 0 {\n\t\treturn nil, fmt.Errorf(\"work item creation failed: %s\", resp.WorkItemCreate.Errors[0])\n\t}\n\tif resp.WorkItemCreate.WorkItem == nil {\n\t\treturn nil, fmt.Errorf(\"work item creation returned nil\")\n\t}\n\n\twi := resp.WorkItemCreate.WorkItem\n\treturn &WorkItem{\n\t\tID:    wi.ID,\n\t\tIID:   wi.IID,\n\t\tTitle: wi.Title,\n\t\tType:  wi.Type.Name,\n\t}, nil\n}\n\n// GetWorkItemGID looks up the global ID of a work item by its project-scoped IID.\nfunc (c *Client) GetWorkItemGID(ctx context.Context, projectPath string, iid int) (string, error) {\n\tquery := fmt.Sprintf(`{\n\t\tproject(fullPath: %q) {\n\t\t\tworkItems(iid: \"%d\", first: 1) {\n\t\t\t\tnodes { id }\n\t\t\t}","sourceCodeStart":612,"sourceCodeEnd":648,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/gitlab/client.go#L612-L648","documentation":"The workItemCreate mutation reported success (no errors array) but returned a nil workItem payload. This is a defensive invariant check in the client: a 'successful' mutation that yields no work item is a broken or edge-case API response, so the client refuses to fabricate a result.","triggerScenarios":"Calling CreateTaskWorkItem against a GitLab instance where the mutation returns 200 with data present but workItem:null — schema drift, a partially rolled out feature, or an instance quirk where errors are reported out-of-band.","commonSituations":"Running against pre-release/beta GitLab builds where workItemCreate's success shape is unstable; schema drift after upgrades; a proxy stripping response fields while keeping status codes.","solutions":["Log the full raw GraphQL response to confirm workItem is truly null.","Upgrade or align the client with the GitLab version's stable workItemCreate schema.","Treat as a server-side anomaly and retry once; if persistent, report against the GitLab instance/version.","Check the instance's GraphQL schema via introspection to confirm the workItem field contract."],"exampleFix":"null","handlingStrategy":"retry","validationCode":"// confirm the instance exposes a stable WorkItem type first\nconst q = `{ __type(name: \"WorkItem\") { fields { name } } }`","typeGuard":null,"tryCatchPattern":"item, err := client.CreateTaskWorkItem(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"work item creation returned nil\") {\n        // possible transient instance anomaly; retry once, then report against the GitLab version\n    }\n    return err\n}","preventionTips":["Avoid pre-release/beta GitLab builds for production integrations.","Verify proxies don't strip response fields while preserving status codes.","Report persistent occurrences to the GitLab instance operators with the raw response."],"tags":["gitlab","graphql","invariant","nil-response"],"backgroundTag":"unexpected-null-response","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}