{"record":{"id":"c56c43ec0cc0b4f5","repo":"gastownhall/beads","slug":"copy-label-q-for-s-w","errorCode":null,"errorMessage":"copy label %q for %s: %w","messagePattern":"copy label %q for (.+?): %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/migrate_personal.go","lineNumber":211,"sourceCode":"\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)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"read comments for %s: %w\", issue.ID, err)\n\t}\n\tfor _, c := range comments {","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/migrate_personal.go#L193-L229","documentation":"After reading labels, copyIssueRelations writes each label to the destination via dst.AddLabel. If any single label write fails, the migration aborts with this error naming the label and issue.","triggerScenarios":"dst.AddLabel(ctx, issue.ID, label, actor) errors — destination DB locked, duplicate label constraint, or driver write failure while copying a specific label.","commonSituations":"Destination .beads DB is open in another bd process (lock conflict), or a prior partial migration left the label already present with a uniqueness constraint.","solutions":["Read the wrapped inner error to identify the failing label and destination driver cause.","Close other bd sessions holding a lock on the destination database.","If duplicates are the cause, clear the partially migrated destination or run migration into a fresh destination, then retry."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"labels, err := src.GetLabels(ctx, issue.ID)\nif err != nil { return err }\n_ = labels // source readable; destination lock still possible","typeGuard":null,"tryCatchPattern":"if err := copyIssueRelations(ctx, src, dst, issue, actor); err != nil {\n    // err contains: copy label \"x\" for <id>: <driver err>\n    if errors.Is(err, storage.ErrLocked) { /* retry after releasing lock */ }\n    return err\n}","preventionTips":["Ensure no concurrent bd session holds the destination DB.","Migrate into a fresh/empty destination to avoid duplicate-label conflicts.","Check the wrapped error's label name to pinpoint the failing row."],"tags":["migration","storage","dolt","labels"],"backgroundTag":"storage-write-failure","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}