gastownhall/beads · error

issue creation reported as unsuccessful

Error message

issue creation reported as unsuccessful

What it means

Linear's issueCreate mutation returns a `success` boolean. If the mutation executed but Linear reported success=false (and no Execute/unmarshal error occurred), CreateIssue returns this error rather than an issue with a null/zero ID. It indicates the mutation was accepted but creation did not happen.

Source

Thrown at internal/linear/client.go:859

// CreateIssue creates a new issue in Linear.
func (c *Client) CreateIssue(ctx context.Context, title, description string, priority int, stateID string, labelIDs []string) (*Issue, error) {
	req := &GraphQLRequest{
		Query:     issueCreateMutation,
		Variables: map[string]interface{}{"input": c.buildIssueCreateInput(title, description, priority, stateID, labelIDs)},
	}

	data, err := c.Execute(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("failed to create issue: %w", err)
	}

	var createResp IssueCreateResponse
	if err := json.Unmarshal(data, &createResp); err != nil {
		return nil, fmt.Errorf("failed to parse create response: %w", err)
	}

	if !createResp.IssueCreate.Success {
		return nil, fmt.Errorf("issue creation reported as unsuccessful")
	}

	return &createResp.IssueCreate.Issue, nil
}

// createIssueSingleAttempt executes the issueCreate mutation exactly once,
// without the retry loop used by Execute. This is intentional: retrying a
// mutation that may have already reached Linear risks creating a duplicate.
// The caller (CreateIssueIdempotent) handles retry safety by re-searching for
// the idempotency marker after any failure.
func (c *Client) createIssueSingleAttempt(ctx context.Context, title, description string, priority int, stateID string, labelIDs []string) (*Issue, error) {
	req := &GraphQLRequest{
		Query:     issueCreateMutation,
		Variables: map[string]interface{}{"input": c.buildIssueCreateInput(title, description, priority, stateID, labelIDs)},
	}

	body, err := json.Marshal(req)
	if err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the full GraphQL response for an `errors` array or detail messages accompanying success=false.
  2. Validate the input against the team's requirements (required fields, limits) before calling CreateIssue.
  3. Check the Linear workspace's plan/issue limits in the Linear admin UI.
  4. Fall back to CreateIssueIdempotent, which retries safely and can surface better diagnostics.

Example fix

// before
if !createResp.IssueCreate.Success {
    return nil, fmt.Errorf("issue creation reported as unsuccessful")
}
// after
if !createResp.IssueCreate.Success {
    return nil, fmt.Errorf("issue creation reported as unsuccessful (lastError: %s)", createResp.IssueCreate.LastError)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check plan limits / required fields before creating
issueCount, _ := countTeamIssues(ctx, client)
if issueCount >= workspaceIssueLimit {
    return errors.New("workspace issue limit reached; issueCreate would report success=false")
}

Try / catch

issue, err := client.CreateIssue(ctx, title, desc, pri, stateID, labels)
if err != nil {
    if strings.Contains(err.Error(), "reported as unsuccessful") {
        log.Printf("Linear rejected creation of %q; check workspace limits/required fields", title)
        return errCreateRejected
    }
    return err
}

Prevention

When it happens

Trigger: Linear responds with issueCreate.success == false — typically due to business-rule rejections (e.g. invalid input slipping past validation), template/team constraints, or the account being over limits (e.g. issue limits on free plans).

Common situations: Workspace hitting plan limits, team requiring certain fields, input referencing archived teams/states that Linear accepts syntactically but rejects logically, unexpected API behavior after partial errors.

Related errors


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