gastownhall/beads · error
failed to create issue: %w
Error message
failed to create issue: %w
What it means
CreateIssue sends the issueCreate GraphQL mutation and wraps any Execute failure with this message. It distinguishes transport/GraphQL failures from application-level 'creation unsuccessful' responses handled later.
Source
Thrown at internal/linear/client.go:850
if stateID != "" {
input["stateId"] = stateID
}
if len(labelIDs) > 0 {
input["labelIds"] = labelIDs
}
return input
}
// 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 forView on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the root cause to identify transport vs. GraphQL validation errors.
- Verify every ID in the input (stateID, labelIDs) is currently valid via the Linear API.
- Check the API key validity and scopes.
- Retry with backoff on 429 or transient network errors; use CreateIssueIdempotent to avoid duplicates on retry.
Example fix
// before
if err != nil {
return nil, fmt.Errorf("failed to create issue: %w", err)
}
// after
if err != nil {
var gqlErr *GraphQLValidationError
if errors.As(err, &gqlErr) {
return nil, fmt.Errorf("failed to create issue (input: state=%s labels=%v): %w", stateID, labelIDs, err)
}
return nil, fmt.Errorf("failed to create issue: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// validate referenced IDs before the mutation
if stateID != "" && !uuidRegex.MatchString(stateID) {
return fmt.Errorf("invalid state ID: %q", stateID)
}
for _, id := range labelIDs {
if !uuidRegex.MatchString(id) {
return fmt.Errorf("invalid label ID: %q", id)
}
} Try / catch
issue, err := client.CreateIssue(ctx, title, desc, pri, stateID, labelIDs)
if err != nil {
if isRateLimit(err) {
time.Sleep(backoff); return retry()
}
return fmt.Errorf("issue %q not created: %w", title, err)
} Prevention
- Refresh state/label caches rather than holding stale UUIDs.
- Prefer CreateIssueIdempotent to make retries safe.
- Validate priority is in Linear's accepted range (0–4).
- Preflight API key and workspace access at startup.
When it happens
Trigger: Execute fails during the issueCreate mutation: network timeout, 401 from a bad API key, 429 rate limit, GraphQL validation errors from an invalid input (bad state ID, nonexistent label IDs, missing required fields in the input map), or duplicate-subscription GraphQL errors.
Common situations: Passing stale workflow-state or label UUIDs (deleted since cached), invalid priority enum value, expired API key, network blips during automated `bd`-to-Linear sync runs.
Related errors
- failed to fetch team labels: %w
- failed to search issues by description: %w
- issue creation reported as unsuccessful
- failed to update project: %w
- project update reported as unsuccessful
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/136853c6163b8b7c.
Report an issue: GitHub.