{"record":{"id":"6662418404938c03","repo":"gastownhall/beads","slug":"failed-to-create-issue-w-666241","errorCode":null,"errorMessage":"failed to create issue: %w","messagePattern":"failed to create issue: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/gitlab/client.go","lineNumber":353,"sourceCode":"\t}\n\n\treturn filterByProject(allIssues, filter), nil\n}\n\n// CreateIssue creates a new issue in GitLab.\nfunc (c *Client) CreateIssue(ctx context.Context, title, description string, labels []string) (*Issue, error) {\n\tbody := map[string]interface{}{\n\t\t\"title\":       title,\n\t\t\"description\": description,\n\t}\n\tif len(labels) > 0 {\n\t\tbody[\"labels\"] = labels\n\t}\n\n\turlStr := c.buildURL(\"/projects/\"+c.projectPath()+\"/issues\", nil)\n\trespBody, _, err := c.doRequest(ctx, http.MethodPost, urlStr, body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create issue: %w\", err)\n\t}\n\n\tvar issue Issue\n\tif err := json.Unmarshal(respBody, &issue); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse create response: %w\", err)\n\t}\n\n\treturn &issue, nil\n}\n\n// UpdateIssue updates an existing issue in GitLab.\nfunc (c *Client) UpdateIssue(ctx context.Context, iid int, updates map[string]interface{}) (*Issue, error) {\n\turlStr := c.buildURL(\"/projects/\"+c.projectPath()+\"/issues/\"+strconv.Itoa(iid), nil)\n\trespBody, _, err := c.doRequest(ctx, http.MethodPut, urlStr, updates)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to update issue: %w\", err)\n\t}\n","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/gitlab/client.go#L335-L371","documentation":"CreateIssue failed at the HTTP layer when POSTing the new issue to GitLab. The library wraps the doRequest error, so the cause (auth, validation, network) is in the wrapped error.","triggerScenarios":"POST /projects/:id/issues fails: 401 bad token, 403 insufficient scope, 400/422 validation (empty title, description too long, invalid label), 404 wrong project path, or network failure.","commonSituations":"Token lacking api/write scope, project path misconfigured (URL-encoded path wrong), title empty or exceeding limits, spam/CAPTCHA protection on the project, or hitting rate limits.","solutions":["Check the wrapped error's status: 401/403 → fix token and scopes (api), 404 → fix project path, 400/422 → fix title/labels payload","Verify token validity: curl -H \"PRIVATE-TOKEN: ...\" /api/v4/user","Confirm projectPath matches the GitLab project (namespace/name, URL-encoded)","Retry with backoff if 429/5xx"],"exampleFix":"// before\nclient.CreateIssue(ctx, \"\", \"description\", nil) // empty title -> 422\n// after\nif title == \"\" { return errors.New(\"title required\") }\nclient.CreateIssue(ctx, title, description, labels)","handlingStrategy":"validation","validationCode":"if strings.TrimSpace(title) == \"\" { return errors.New(\"issue title is required\") }\nif len(description) > 1000000 { return errors.New(\"description too long\") }\n// verify token write access\nresp, _ := http.Get(baseURL + \"/api/v4/user\") // 200 means token valid","typeGuard":"func isCreateRejected(err error) bool {\n\ts := err.Error()\n\treturn strings.Contains(s, \"failed to create issue\")\n}","tryCatchPattern":"issue, err := client.CreateIssue(ctx, title, desc, labels)\nif err != nil {\n\tswitch {\n\tcase strings.Contains(err.Error(), \"401\"), strings.Contains(err.Error(), \"403\"):\n\t\treturn fmt.Errorf(\"check token scopes: %w\", err)\n\tcase strings.Contains(err.Error(), \"429\"):\n\t\ttime.Sleep(time.Second); // retry\n\tdefault:\n\t\treturn err\n\t}\n}","preventionTips":["Use a token with api scope and verify project write access before creating issues","Validate title/labels against GitLab limits before calling","URL-encode the project path correctly in client config","Handle 429 with exponential backoff"],"tags":["gitlab","network","auth"],"backgroundTag":"http-request-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}