gastownhall/beads · error
failed to remove relates-to %s -> %s: %w
Error message
failed to remove relates-to %s -> %s: %w
What it means
runUnrelate removes the relates-to dependency in both directions using store.RemoveDependencyWithOptions with EmitEvent: true (per Decision 004, relates-to links live in the dependencies table and unrelate records history). This wraps a storage error from the first removal, id1 -> id2. Both issues were already verified to exist, so this is a dependency-table write failure, not a missing record.
Source
Thrown at cmd/bd/relate.go:194
issue2, err = store.GetIssue(ctx, id2)
if err != nil {
return fmt.Errorf("failed to get issue %s: %w", id2, err)
}
if issue1 == nil {
return fmt.Errorf("issue not found: %s", id1)
}
if issue2 == nil {
return fmt.Errorf("issue not found: %s", id2)
}
// Remove relates-to dependency in both directions
// Per Decision 004, relates-to links are now stored in dependencies table.
// bd unrelate is an explicit dependency verb, so it records history
// (EmitEvent) like bd dep remove; only structural teardown stays silent.
// Remove id1 -> id2
if err := store.RemoveDependencyWithOptions(ctx, id1, id2, actor, storage.DependencyRemoveOptions{EmitEvent: true}); err != nil {
return fmt.Errorf("failed to remove relates-to %s -> %s: %w", id1, id2, err)
}
// Remove id2 -> id1 (bidirectional)
if err := store.RemoveDependencyWithOptions(ctx, id2, id1, actor, storage.DependencyRemoveOptions{EmitEvent: true}); err != nil {
return fmt.Errorf("failed to remove relates-to %s -> %s: %w", id2, id1, err)
}
if jsonOutput {
result := map[string]interface{}{
"id1": id1,
"id2": id2,
"unrelated": true,
}
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")
return encoder.Encode(result)
}
fmt.Printf("%s Unlinked %s ↔ %s\n", ui.RenderPass("✓"), id1, id2)View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped inner error to identify the storage failure (lock vs constraint vs I/O) and address that cause directly.
- If it is a lock, wait for the other bd process / `bd dolt` command to finish and rerun the unrelate; serialize writers.
- Run `bd doctor` to check database health; if the dependencies table is inconsistent, follow its repair guidance or restore from backup and re-sync.
- Ensure both endpoints use consistent bd versions — upgrade/downgrade so the writer matches the schema that created the dependency rows.
- Retry after transient I/O failures; the removal is a single transaction so a partial delete-without-event should not persist.
Example fix
// before $ bd unrelate bd-1 bd-2 & bd dolt push & # concurrent writers failed to remove relates-to bd-1 -> bd-2: database is locked // after $ bd dolt push && bd unrelate bd-1 bd-2 # run storage ops sequentially
Defensive patterns
Strategy: try-catch
Validate before calling
// both issues verified to exist; check storage writability before mutating
if err := store.RunInTransaction(ctx, func(tx storage.Tx) error { return nil }); err != nil {
return fmt.Errorf("storage not writable: %w", err)
} Try / catch
err := store.RemoveDependencyWithOptions(ctx, id1, id2, actor, storage.DependencyRemoveOptions{EmitEvent: true})
if err != nil {
if errors.Is(err, ErrDatabaseLocked) {
// serialize with other writers, then retry once
time.Sleep(time.Second)
err = store.RemoveDependencyWithOptions(ctx, id1, id2, actor, storage.DependencyRemoveOptions{EmitEvent: true})
}
if err != nil {
return fmt.Errorf("failed to remove relates-to %s -> %s: %w", id1, id2, err)
}
} Prevention
- Avoid running bd mutations concurrently with `bd dolt push/pull` in the same repo.
- Keep bd versions consistent across machines touching the same database to avoid schema skew.
- Run `bd doctor` after unexpected crashes to catch dependencies-table corruption early.
- Back up or rely on git-synced export before bulk unrelate operations.
When it happens
Trigger: store.RemoveDependencyWithOptions(ctx, id1, id2, actor, {EmitEvent:true}) errors: database locked by a concurrent writer, constraint or driver error deleting the dependency row, EmitEvent history write failing, or storage corruption in the dependencies table.
Common situations: Concurrent `bd dep`/sync operations holding a write lock; a half-migrated dependencies table (older bd version created the data); disk I/O failure during the delete-plus-event transaction; corrupted Dolt store after a crash.
Related errors
- failed to get issue %s: %w
- no store is open for this workspace
- load dependency records: %w
- get molecule children: %w
- failed to get dependencies for %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/81f4a4dd0f2945a8.
Report an issue: GitHub.