gastownhall/beads · error
issue update reported as unsuccessful
Error message
issue update reported as unsuccessful
What it means
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.
Source
Thrown at internal/linear/client.go:1019
Query: query,
Variables: map[string]interface{}{
"id": issueID,
"input": updates,
},
}
data, err := c.Execute(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to update issue: %w", err)
}
var updateResp IssueUpdateResponse
if err := json.Unmarshal(data, &updateResp); err != nil {
return nil, fmt.Errorf("failed to parse update response: %w", err)
}
if !updateResp.IssueUpdate.Success {
return nil, fmt.Errorf("issue update reported as unsuccessful")
}
return &updateResp.IssueUpdate.Issue, nil
}
// BatchCreateIssues creates multiple issues in Linear using the issueBatchCreate mutation.
// Inputs are chunked into groups of BatchSize (50).
//
// On ambiguous failure (API error or success=false), this method does NOT blindly
// retry the full chunk—Linear may have partially applied the mutation. Instead it
// searches for each issue's idempotency marker (embedded in the description) to
// discover which issues were actually created, and returns an error for the rest.
func (c *Client) BatchCreateIssues(ctx context.Context, inputs []IssueCreateInput) ([]Issue, error) {
if len(inputs) == 0 {
return nil, nil
}
query := `View on GitHub (pinned to 71377f2769)
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.
Example fix
// before
issue, err := client.UpdateIssue(ctx, "ENG-123", IssueUpdateInput{Priority: &p})
// after
id, _ := resolveLinearUUID(ctx, client, "ENG-123") // query Linear for the UUID
issue, err := client.UpdateIssue(ctx, id, IssueUpdateInput{Priority: &p}) Defensive patterns
Strategy: validation
Validate before calling
// Resolve the UUID and check writability before calling UpdateIssue
issue, err := client.FindIssueByID(ctx, issueRef) // or identifier lookup
if err != nil || issue == nil {
return fmt.Errorf("issue %s not found or inaccessible: %w", issueRef, err)
}
// use issue.ID (UUID) in UpdateIssue Type guard
func isUpdateRejected(err error) bool {
return err != nil && strings.Contains(err.Error(), "issue update reported as unsuccessful")
} Try / catch
issue, err := client.UpdateIssue(ctx, id, updates)
if isUpdateRejected(err) {
// Linear refused the mutation: check id, token scopes, and field values
return fmt.Errorf("linear rejected update for %s: %w", id, err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- work item creation failed: %s
- GraphQL error: %s
- GraphQL errors: %s
- no states found for team
- no labels connection found for team
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d8beb148c2d5dc72.
Report an issue: GitHub.