gastownhall/beads · error
dependencies: %w
Error message
dependencies: %w
What it means
rekeyDependencyIDs rewrites dependencies.id values to deterministic depid.New(issue_id, target) values so independently-migrated clones converge and `bd dolt pull` works. This error wraps any failure from the re-key pass over the dependencies table specifically (the wisp_dependencies variant has its own wrapper).
Source
Thrown at internal/storage/schema/dep_id_backfill.go:32
//
// Migration 0043 minted dependencies.id from DEFAULT (UUID()), which is
// per-clone-random; migration 0050 + the deterministic insert paths fix new
// rows, but rows that already exist on an upgrading clone still carry the random
// id. Leaving them would keep two independently-migrated clones divergent (same
// edge, different primary key) and break `bd dolt pull`. This rewrites them to
// the deterministic value so two clones converge to byte-identical dependencies.
//
// It runs from MigrateUp right after the schema migrations (so 0050 has already
// asserted the canonical schema), and only on a pass where migration work was
// needed — it is not part of the steady-state open path. It is idempotent: a row
// already keyed deterministically is skipped, so re-running on a later migration
// pass is a cheap no-op. dependencies changes are staged and committed by
// MigrateUp; wisp_dependencies is dolt-ignored, so its re-key stays clone-local
// (it only escapes on promotion, which copies the id).
func rekeyDependencyIDs(ctx context.Context, db DBConn) (bool, error) {
wroteDeps, err := rekeyDependencyTable(ctx, db, "dependencies")
if err != nil {
return wroteDeps, fmt.Errorf("dependencies: %w", err)
}
wroteWisp, err := rekeyDependencyTable(ctx, db, "wisp_dependencies")
if err != nil {
return wroteDeps || wroteWisp, fmt.Errorf("wisp_dependencies: %w", err)
}
return wroteDeps || wroteWisp, nil
}
// rekeyDependencyTable re-derives ids for one edge table. table must be a
// hardcoded constant ("dependencies" or "wisp_dependencies").
func rekeyDependencyTable(ctx context.Context, db DBConn, table string) (bool, error) {
// Skip cleanly if the table or its id column isn't present (e.g. an older or
// partial schema where the surrogate key was never added): nothing to re-key.
hasID, err := columnExists(ctx, db, table, "id")
if err != nil {
return false, err
}
if !hasID {View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped inner error (from the SELECT/UPDATE inside rekeyDependencyTable) for the root cause
- Check for unique-key violations: duplicate (issue_id, target) edges collide on the same deterministic id — dedupe them
- Re-run the migration pass — the re-key is idempotent and resumes
- If the schema predates migration 0043/0050, run the full migration path (normal MigrateUp) rather than partial copies
Defensive patterns
Strategy: try-catch
Validate before calling
-- detect rows needing rekey and duplicates before migrating SELECT issue_id, COALESCE(depends_on_issue_id, depends_on_wisp_id, depends_on_external) t, COUNT(*) c FROM dependencies GROUP BY issue_id, t HAVING c > 1;
Try / catch
if _, err := rekeyDependencyIDs(ctx, db); err != nil {
if dberrors.IsUniqueViolation(err) {
return fmt.Errorf("duplicate dependency edges; dedupe before rekey: %w", err)
}
return err
} Prevention
- Run full MigrateUp rather than copying tables between clones partially
- Ensure migration 0050 schema is applied before data backfills
- Backup the database before upgrading old clones
When it happens
Trigger: rekeyDependencyTable(ctx, db, "dependencies") fails — columnExists probe error, the SELECT of (id, issue_id, COALESCE(...)) fails, row scan failure, rows.Err(), or an UPDATE during the re-key loop errors.
Common situations: Upgrading an old clone whose dependencies table has pre-0050 UUID ids; connection drop mid-migration; a malformed row or unique-key conflict when two edges map to the same deterministic id; schema drift where the id column layout differs.
Related errors
- wisp_dependencies: %w
- load dependency records: %w
- load dependency counts: %w
- load wisp dependency counts: %w
- read dependencies for %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/9c3f64fa55000e0a.
Report an issue: GitHub.