{"record":{"id":"d8beb148c2d5dc72","repo":"gastownhall/beads","slug":"issue-update-reported-as-unsuccessful","errorCode":null,"errorMessage":"issue update reported as unsuccessful","messagePattern":"issue update reported as unsuccessful","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/linear/client.go","lineNumber":1019,"sourceCode":"\t\tQuery: query,\n\t\tVariables: map[string]interface{}{\n\t\t\t\"id\":    issueID,\n\t\t\t\"input\": updates,\n\t\t},\n\t}\n\n\tdata, err := c.Execute(ctx, req)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to update issue: %w\", err)\n\t}\n\n\tvar updateResp IssueUpdateResponse\n\tif err := json.Unmarshal(data, &updateResp); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse update response: %w\", err)\n\t}\n\n\tif !updateResp.IssueUpdate.Success {\n\t\treturn nil, fmt.Errorf(\"issue update reported as unsuccessful\")\n\t}\n\n\treturn &updateResp.IssueUpdate.Issue, nil\n}\n\n// BatchCreateIssues creates multiple issues in Linear using the issueBatchCreate mutation.\n// Inputs are chunked into groups of BatchSize (50).\n//\n// On ambiguous failure (API error or success=false), this method does NOT blindly\n// retry the full chunk—Linear may have partially applied the mutation. Instead it\n// searches for each issue's idempotency marker (embedded in the description) to\n// discover which issues were actually created, and returns an error for the rest.\nfunc (c *Client) BatchCreateIssues(ctx context.Context, inputs []IssueCreateInput) ([]Issue, error) {\n\tif len(inputs) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tquery := `","sourceCodeStart":1001,"sourceCodeEnd":1037,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/linear/client.go#L1001-L1037","documentation":"After successfully decoding the GraphQL response, UpdateIssue checks the mutation's success flag (issueUpdate.success). Linear itself reported success=false, so the library returns this error instead of a nil issue. The update was NOT applied; the response body was well-formed and reachable.","triggerScenarios":"Calling Client.UpdateIssue with a payload Linear rejects at the mutation level: invalid issue ID, permission denied for the team/project, an invalid field value in the updates input (e.g. bad state ID or priority), or archived/deleted issue.","commonSituations":"Using an issue identifier (e.g. ENG-123) instead of Linear's UUID id; stale state IDs cached from an old workflow; API token lacking write scope for that team; issue archived by someone else mid-flight.","solutions":["Confirm you pass Linear's UUID id (not the human identifier); resolve identifiers via a query first.","Check the API token's scopes and team membership for the target issue.","Validate field values in the updates input (state/priority/assignee IDs) against current Linear data.","Re-fetch the issue to confirm it still exists and is not archived, then retry."],"exampleFix":"// before\nissue, err := client.UpdateIssue(ctx, \"ENG-123\", IssueUpdateInput{Priority: &p})\n// after\nid, _ := resolveLinearUUID(ctx, client, \"ENG-123\") // query Linear for the UUID\nissue, err := client.UpdateIssue(ctx, id, IssueUpdateInput{Priority: &p})","handlingStrategy":"validation","validationCode":"// Resolve the UUID and check writability before calling UpdateIssue\nissue, err := client.FindIssueByID(ctx, issueRef) // or identifier lookup\nif err != nil || issue == nil {\n    return fmt.Errorf(\"issue %s not found or inaccessible: %w\", issueRef, err)\n}\n// use issue.ID (UUID) in UpdateIssue","typeGuard":"func isUpdateRejected(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"issue update reported as unsuccessful\")\n}","tryCatchPattern":"issue, err := client.UpdateIssue(ctx, id, updates)\nif isUpdateRejected(err) {\n    // Linear refused the mutation: check id, token scopes, and field values\n    return fmt.Errorf(\"linear rejected update for %s: %w\", id, err)\n}","preventionTips":["Always pass Linear UUIDs, never human identifiers like ENG-123.","Refresh cached state/assignee IDs before updates; workflow states change.","Ensure the API token has write scope for the target team.","Re-fetch the issue before updating to catch archived/deleted issues."],"tags":["linear-api","graphql","permissions","validation","api-response"],"backgroundTag":"mutation-unsuccessful","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}