gastownhall/beads · error

batch create failed; %d of %d issues unconfirmed (batch erro

Error message

batch create failed; %d of %d issues unconfirmed (batch error: %v)

What it means

In BatchCreateIssues, the issueBatchCreate request failed, recovery search ran successfully, but it confirmed fewer issues than the chunk contained — meaning some issues in the chunk were never created in Linear (or could not be found because their descriptions lack the idempotency marker). The method returns all issues confirmed so far plus this error stating how many of the chunk's issues are unconfirmed.

Source

Thrown at internal/linear/client.go:1084

		req := &GraphQLRequest{
			Query: query,
			Variables: map[string]interface{}{
				"input": map[string]interface{}{
					"issues": chunk,
				},
			},
		}

		data, err := c.Execute(ctx, req)
		if err != nil {
			found, recoverErr := c.recoverAfterAmbiguousBatch(ctx, chunk)
			if recoverErr != nil {
				return allIssues, fmt.Errorf("batch create failed and recovery search also failed: %w (batch error: %v)", recoverErr, err)
			}
			allIssues = append(allIssues, found...)
			if len(found) < len(chunk) {
				return allIssues, fmt.Errorf("batch create failed; %d of %d issues unconfirmed (batch error: %v)", len(chunk)-len(found), len(chunk), err)
			}
			continue
		}

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

		if !batchResp.IssueBatchCreate.Success {
			found, recoverErr := c.recoverAfterAmbiguousBatch(ctx, chunk)
			if recoverErr != nil {
				return allIssues, fmt.Errorf("batch create unsuccessful and recovery search also failed: %w", recoverErr)
			}
			allIssues = append(allIssues, found...)
			if len(found) < len(chunk) {
				return allIssues, fmt.Errorf("batch create unsuccessful; %d of %d issues unconfirmed", len(chunk)-len(found), len(chunk))
			}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure every IssueCreateInput.Description includes the <!-- bd-idempotency: ... --> marker before calling BatchCreateIssues.
  2. Retry the failed chunk with the same markers; Linear-side idempotent recovery will skip already-created issues.
  3. Search Linear for the missing issues' markers manually to confirm which are truly absent.
  4. Retry after resolving the transient network condition noted in the batch error portion.

Example fix

// before
input := IssueCreateInput{Title: "Bug", Description: desc}
// after
input := IssueCreateInput{Title: "Bug", Description: desc + "\n<!-- bd-idempotency: " + marker + " -->"}
Defensive patterns

Strategy: retry

Validate before calling

// Verify every input description carries a unique idempotency marker
seen := map[string]bool{}
for _, in := range inputs {
    m := extractMarker(in.Description) // must contain <!-- bd-idempotency: ... -->
    if m == "" || seen[m] {
        return errors.New("missing or duplicate idempotency marker in batch inputs")
    }
    seen[m] = true
}

Type guard

func hasUnconfirmedIssues(err error) bool {
    return err != nil && strings.Contains(err.Error(), "issues unconfirmed")
}

Try / catch

issues, err := client.BatchCreateIssues(ctx, inputs)
if hasUnconfirmedIssues(err) {
    // issues may hold confirmed ones; retry ONLY the missing items with the same markers
    missing := diffByMarker(inputs, issues)
    issues2, err2 := client.BatchCreateIssues(ctx, missing)
}

Prevention

When it happens

Trigger: Calling Client.BatchCreateIssues where c.Execute errors for a chunk, and recoverAfterAmbiguousBatch finds fewer issues than len(chunk) — typically because some inputs' descriptions have no <!-- bd-idempotency: ... --> marker (extractIdempotencyMarker returns "" and the issue is skipped), or the issues genuinely were never created.

Common situations: Passing IssueCreateInput values whose Description was built without the idempotency marker appended; network drops mid-batch so part of the chunk landed server-side and part did not; markers altered/escaped by downstream description transforms.

Related errors


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