{"record":{"id":"47c12d3db6b3f3e4","repo":"gastownhall/beads","slug":"read-labels-for-s-w","errorCode":null,"errorMessage":"read labels for %s: %w","messagePattern":"read labels for (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/migrate_personal.go","lineNumber":207,"sourceCode":"\n\tfmt.Printf(\"\\n%s Moved %d %s to %s\\n\",\n\t\tui.RenderPass(\"✓\"),\n\t\tlen(personal),\n\t\tpluralIssue(len(personal)),\n\t\tui.RenderAccent(planningPath))\n\treturn nil\n}\n\n// copyIssueRelations copies the labels, dependency records, and comments for a\n// single issue from src to dst. The issue row itself must already exist in dst\n// (created in phase 1a of runMigratePersonal). Every step — including the reads\n// from src — is fatal on error so the caller can abort the migration before any\n// source data is deleted; a partial copy must never be mistaken for success\n// (maphew review, be-e2nb).\nfunc copyIssueRelations(ctx context.Context, src, dst storage.DoltStorage, issue *types.Issue, actor string) error {\n\tlabels, err := src.GetLabels(ctx, issue.ID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read labels for %s: %w\", issue.ID, err)\n\t}\n\tfor _, label := range labels {\n\t\tif err := dst.AddLabel(ctx, issue.ID, label, actor); err != nil {\n\t\t\treturn fmt.Errorf(\"copy label %q for %s: %w\", label, issue.ID, err)\n\t\t}\n\t}\n\n\tdeps, err := src.GetDependencyRecords(ctx, issue.ID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read dependencies for %s: %w\", issue.ID, err)\n\t}\n\tfor _, dep := range deps {\n\t\tif err := dst.AddDependency(ctx, dep, actor); err != nil {\n\t\t\treturn fmt.Errorf(\"copy dependency %s→%s: %w\", dep.IssueID, dep.DependsOnID, err)\n\t\t}\n\t}\n\n\tcomments, err := src.GetIssueComments(ctx, issue.ID)","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/migrate_personal.go#L189-L225","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// before migrating, verify source storage is readable\nif _, err := src.GetLabels(ctx, issue.ID); err != nil {\n    return fmt.Errorf(\"pre-flight: source labels unreadable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := copyIssueRelations(ctx, src, dst, issue, actor); err != nil {\n    var inner error\n    errors.As(err, &inner) // log full chain: read labels for <id>: <driver err>\n    return err // abort migration; source must remain intact\n}","preventionTips":["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."],"tags":["migration","storage","dolt","labels"],"backgroundTag":"storage-read-failure","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}