gastownhall/beads · error
coordinate issue create: %w
Error message
coordinate issue create: %w
What it means
EnsureIssueIDAvailableInTx fails while writing the per-ID coordination row into local_metadata (REPLACE INTO local_metadata). This write serializes same-shard creates so two concurrent creates of the same ID cannot interleave; failure means the underlying transaction/DB rejected the write.
Source
Thrown at internal/storage/issueops/create_only_guard.go:22
"context"
"crypto/sha256"
"fmt"
"strconv"
"github.com/steveyegge/beads/internal/storage"
)
// EnsureIssueIDAvailableInTx serializes same-shard creates and rejects occupied IDs.
func EnsureIssueIDAvailableInTx(ctx context.Context, tx DBTX, id string) error {
if tx == nil {
return fmt.Errorf("ensure issue ID available: transaction is nil")
}
if id == "" {
return fmt.Errorf("ensure issue ID available: ID is empty")
}
key := issueCreateCoordinationKey(id)
if _, err := tx.ExecContext(ctx, "REPLACE INTO local_metadata (`key`, value) VALUES (?, ?)", key, strconv.FormatInt(FreshRowLock(), 10)); err != nil {
return fmt.Errorf("coordinate issue create: %w", err)
}
for _, table := range []string{"issues", "wisps"} {
var count int
if err := tx.QueryRowContext(ctx, "SELECT COUNT(*) FROM "+table+" WHERE id = ?", id).Scan(&count); err != nil {
return fmt.Errorf("check %s for issue %q: %w", table, id, err)
}
if count > 0 {
return fmt.Errorf("%w: %s", storage.ErrAlreadyExists, id)
}
}
return nil
}
func issueCreateCoordinationKey(id string) string {
sum := sha256.Sum256([]byte(id))
shard := uint16(sum[0])<<4 | uint16(sum[1])>>4
return fmt.Sprintf("issue-create/v1/%03x", shard)
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped driver error via errors.Unwrap to identify the storage-level cause
- Retry the whole transaction with a fresh tx handle; never reuse a failed tx
- Reduce transaction scope/duration so the connection does not time out before the guard runs
Example fix
// before
err := EnsureIssueIDAvailableInTx(ctx, staleTx, id) // tx already rolled back
// after
tx, err := db.BeginTx(ctx, nil)
if err != nil { return err }
err = EnsureIssueIDAvailableInTx(ctx, tx, id) Defensive patterns
Strategy: retry
Try / catch
if err := EnsureIssueIDAvailableInTx(ctx, tx, id); err != nil {
if strings.HasPrefix(err.Error(), "coordinate issue create:") {
cause := errors.Unwrap(err) // inspect driver error
// abandon tx, begin a new one, retry once
}
return err
} Prevention
- Keep transactions short so the connection stays healthy
- Retry at the transaction boundary, never inside a failed tx
- Monitor DB locks/read-only state in the deployment
When it happens
Trigger: The tx handle is dead or already failed (rolled back, closed connection); storage backend error on the local_metadata REPLACE; context canceled mid-exec.
Common situations: Long transactions that hit connection timeouts before reaching the guard; a DB in read-only or locked state; driver-level errors during concurrent batch imports.
Related errors
- ErrTransaction
- open unit of work: %w
- failed to begin transaction: %w
- failed to commit is_blocked repairs: %w
- failed to begin transaction: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/2878c6e325bd996e.
Report an issue: GitHub.