gastownhall/beads · error
read labels for %s: %w
Error message
read labels for %s: %w
What it means
copyIssueRelations reads an issue's labels from the source database before copying them to the destination. If src.GetLabels fails (storage/driver error), the whole migration aborts with this wrapped error so no partial copy is mistaken for success.
Source
Thrown at cmd/bd/migrate_personal.go:207
fmt.Printf("\n%s Moved %d %s to %s\n",
ui.RenderPass("✓"),
len(personal),
pluralIssue(len(personal)),
ui.RenderAccent(planningPath))
return nil
}
// copyIssueRelations copies the labels, dependency records, and comments for a
// single issue from src to dst. The issue row itself must already exist in dst
// (created in phase 1a of runMigratePersonal). Every step — including the reads
// from src — is fatal on error so the caller can abort the migration before any
// source data is deleted; a partial copy must never be mistaken for success
// (maphew review, be-e2nb).
func copyIssueRelations(ctx context.Context, src, dst storage.DoltStorage, issue *types.Issue, actor string) error {
labels, err := src.GetLabels(ctx, issue.ID)
if err != nil {
return fmt.Errorf("read labels for %s: %w", issue.ID, err)
}
for _, label := range labels {
if err := dst.AddLabel(ctx, issue.ID, label, actor); err != nil {
return fmt.Errorf("copy label %q for %s: %w", label, issue.ID, err)
}
}
deps, err := src.GetDependencyRecords(ctx, issue.ID)
if err != nil {
return fmt.Errorf("read dependencies for %s: %w", issue.ID, err)
}
for _, dep := range deps {
if err := dst.AddDependency(ctx, dep, actor); err != nil {
return fmt.Errorf("copy dependency %s→%s: %w", dep.IssueID, dep.DependsOnID, err)
}
}
comments, err := src.GetIssueComments(ctx, issue.ID)View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped inner error (%w) for the underlying driver message and fix storage access (close other bd processes, unlock the DB).
- Verify the source database opens correctly: run bd doctor or a simple bd list against the source path before re-running migration.
- Re-run bd migrate-personal after fixing storage; the fatal-on-error design means retry is safe.
Defensive patterns
Strategy: try-catch
Validate before calling
// before migrating, verify source storage is readable
if _, err := src.GetLabels(ctx, issue.ID); err != nil {
return fmt.Errorf("pre-flight: source labels unreadable: %w", err)
} Try / catch
if err := copyIssueRelations(ctx, src, dst, issue, actor); err != nil {
var inner error
errors.As(err, &inner) // log full chain: read labels for <id>: <driver err>
return err // abort migration; source must remain intact
} Prevention
- Close other bd processes before migrating to avoid DB locks.
- Run bd doctor against the source DB before migration.
- Re-run migration after fixing storage — the fatal-on-error design keeps the source safe.
When it happens
Trigger: src.GetLabels(ctx, issue.ID) returns an error during migration — e.g. source DB locked, corrupted label rows, or Dolt driver failure while reading labels for an issue.
Common situations: Migrating a personal repo whose source .beads Dolt DB is locked by another bd process, or whose label table was corrupted by an interrupted prior migration.
Related errors
- copy label %q for %s: %w
- read dependencies for %s: %w
- copy dependency %s→%s: %w
- read comments for %s: %w
- copy comment for %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/47c12d3db6b3f3e4.
Report an issue: GitHub.