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

  1. Confirm you pass Linear's UUID id (not the human identifier); resolve identifiers via a query first.
  2. Check the API token's scopes and team membership for the target issue.
  3. Validate field values in the updates input (state/priority/assignee IDs) against current Linear data.
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/d8beb148c2d5dc72. Report an issue: GitHub.