gastownhall/beads · error

failed to create issues: %w

Error message

failed to create issues: %w

What it means

Wraps a failure from tx.CreateIssues during the cook --persist transaction. All proto issues generated from the formula are inserted in one transaction; if any insert is rejected (validation, ID conflict, storage error), the message reports it and the whole transaction rolls back so no partial molecule is persisted.

Source

Thrown at cmd/bd/cook.go:913

	// Collect dependencies from depends_on
	for _, step := range f.Steps {
		collectDependencies(step, idMapping, &deps)
	}

	// Create issues, labels, and dependencies in a single atomic transaction.
	// This prevents orphaned issues if label/dependency creation fails.
	err := transact(ctx, s, fmt.Sprintf("bd: cook formula %s", protoID), func(tx storage.Transaction) error {
		// Flatten unregistered step types to task (with a warning) before
		// inserting, mirroring cloneSubgraphInto (pour). Without this,
		// PrepareIssueForInsert rejects them with "invalid issue type" and
		// the whole cook --persist transaction rolls back.
		if err := flattenUnregisteredIssueTypes(ctx, storeMolWriter{DoltStorage: s, tx: tx}, issues, deps); err != nil {
			return fmt.Errorf("checking custom types: %w", err)
		}

		// Create all issues
		if err := tx.CreateIssues(ctx, issues, actor); err != nil {
			return fmt.Errorf("failed to create issues: %w", err)
		}

		// Add labels
		for _, l := range labels {
			if err := tx.AddLabel(ctx, l.issueID, l.label, actor); err != nil {
				return fmt.Errorf("failed to add label %s to %s: %w", l.label, l.issueID, err)
			}
		}

		// Add dependencies
		for _, dep := range deps {
			if err := tx.AddDependency(ctx, dep, actor); err != nil {
				return fmt.Errorf("failed to create dependency: %w", err)
			}
		}

		return nil
	})

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause to identify the offending issue; check for an ID conflict with an existing bead and remove/rename it
  2. Validate generated fields (type, priority, status) are legal values before persisting
  3. Re-run after a transient storage error — the transaction rolled back so state is clean
  4. Check database health (`bd doctor`) if CreateIssues fails repeatedly
  5. Use a distinct --prefix for proto IDs to avoid collisions across runs

Example fix

# before
bd cook --persist formula-name   # proto ID collides with existing bead
# after
bd cook --persist formula-name --prefix molt-   # unique prefix per run
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check for proto ID collisions before persisting
for _, iss := range issues {
    if existing, _ := s.GetIssue(ctx, iss.ID); existing != nil {
        return fmt.Errorf("issue %s already exists; choose another --prefix", iss.ID)
    }
}

Try / catch

if err := tx.CreateIssues(ctx, issues, actor); err != nil {
    return fmt.Errorf("failed to create issues: %w", err) // transaction rolls back
}
// at call site:
if strings.Contains(err.Error(), "failed to create issues") {
    // inspect cause: ID conflict → remove stale proto or change --prefix; then retry
}

Prevention

When it happens

Trigger: tx.CreateIssues rejects one of the generated issues: invalid field values after flattening, duplicate/conflicting issue ID (protoID collision), constraint violation, or underlying Dolt storage error during the write.

Common situations: Proto ID already exists in the database from a previous cook run; an issue field (priority, status, type) violates validation; database locked or corrupted; disk full during write.

Related errors


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