{"record":{"id":"c44bebc452d6cf3b","repo":"gastownhall/beads","slug":"failed-to-update-issue-w-c44beb","errorCode":null,"errorMessage":"failed to update issue: %w","messagePattern":"failed to update issue: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/gitlab/client.go","lineNumber":369,"sourceCode":"\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\n\tvar issue Issue\n\tif err := json.Unmarshal(respBody, &issue); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse update response: %w\", err)\n\t}\n\n\treturn &issue, nil\n}\n\n// GetIssueLinks retrieves issue links for the specified issue IID.\nfunc (c *Client) GetIssueLinks(ctx context.Context, iid int) ([]IssueLink, error) {\n\turlStr := c.buildURL(\"/projects/\"+c.projectPath()+\"/issues/\"+strconv.Itoa(iid)+\"/links\", nil)\n\trespBody, _, err := c.doRequest(ctx, http.MethodGet, urlStr, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get issue links: %w\", err)\n\t}\n","sourceCodeStart":351,"sourceCodeEnd":387,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/gitlab/client.go#L351-L387","documentation":"UpdateIssue failed at the HTTP layer when PUTting updates to an existing issue identified by IID. The cause is wrapped from doRequest.","triggerScenarios":"PUT /projects/:id/issues/:iid fails: 404 (IID not found in the configured project or project path wrong), 400/422 invalid update keys or values, 401/403 token lacks write access, or network/context error.","commonSituations":"Passing an IID from a different project, sending update keys GitLab rejects (e.g. bad state_event, malformed labels), token without api scope, or updating a closed/locked issue without permission.","solutions":["Verify the IID exists in the configured project (FetchIssueByIID first)","Check wrapped status: 404 → fix projectPath/iid, 403 → token scope, 400/422 → fix update keys/values","Use valid state_event values (\"close\", \"reopen\") and correct label formats","Check issue confidentiality/lock settings if 403 persists"],"exampleFix":"// before\nclient.UpdateIssue(ctx, 123, map[string]interface{}{\"state\": \"closed\"}) // invalid key\n// after\nclient.UpdateIssue(ctx, 123, map[string]interface{}{\"state_event\": \"close\"})","handlingStrategy":"validation","validationCode":"if iid <= 0 { return errors.New(\"invalid iid\") }\nif _, err := client.FetchIssueByIID(ctx, iid); err != nil {\n\treturn fmt.Errorf(\"iid %d not found in configured project: %w\", iid, err)\n}","typeGuard":"func isUpdateRejected(err error) bool {\n\treturn strings.Contains(err.Error(), \"failed to update issue\")\n}","tryCatchPattern":"issue, err := client.UpdateIssue(ctx, iid, updates)\nif err != nil {\n\tif strings.Contains(err.Error(), \"404\") { return fmt.Errorf(\"issue iid %d not found: %w\", iid, err) }\n\tif strings.Contains(err.Error(), \"403\") { return fmt.Errorf(\"token lacks write access: %w\", err) }\n\treturn err\n}","preventionTips":["Validate update keys against the GitLab issues API (state_event, not state)","Use iids scoped to the configured project only","Ensure token has api scope for writes","Fetch the issue first to confirm existence and permissions"],"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"}