{"record":{"id":"944fe205ca28c114","repo":"gastownhall/beads","slug":"cannot-mark-an-issue-as-duplicate-of-itself","errorCode":null,"errorMessage":"cannot mark an issue as duplicate of itself","messagePattern":"cannot mark an issue as duplicate of itself","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/duplicate.go","lineNumber":90,"sourceCode":"\n\tctx := getRootContext()\n\tstore := getStore()\n\tactor := getActor()\n\n\t// Resolve partial IDs\n\tvar duplicateID, canonicalID string\n\tvar err error\n\tduplicateID, err = utils.ResolvePartialID(ctx, store, args[0])\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to resolve %s: %w\", args[0], err)\n\t}\n\tcanonicalID, err = utils.ResolvePartialID(ctx, store, duplicateOf)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to resolve %s: %w\", duplicateOf, err)\n\t}\n\n\tif duplicateID == canonicalID {\n\t\treturn fmt.Errorf(\"cannot mark an issue as duplicate of itself\")\n\t}\n\n\t// Verify canonical issue exists\n\tvar canonical *types.Issue\n\tcanonical, err = store.GetIssue(ctx, canonicalID)\n\tif err != nil || canonical == nil {\n\t\treturn fmt.Errorf(\"canonical issue not found: %s\", canonicalID)\n\t}\n\n\t// Add a \"duplicates\" dependency edge (duplicate → canonical)\n\tdep := &types.Dependency{\n\t\tIssueID:     duplicateID,\n\t\tDependsOnID: canonicalID,\n\t\tType:        types.DepDuplicates,\n\t}\n\tif err := store.AddDependency(ctx, dep, actor); err != nil {\n\t\treturn fmt.Errorf(\"failed to add duplicate link: %w\", err)\n\t}","sourceCodeStart":72,"sourceCodeEnd":108,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/duplicate.go#L72-L108","documentation":"A self-duplicate guard in runDuplicate: after resolving both IDs, the duplicate and canonical IDs are identical, so marking it as a duplicate of itself is rejected. This is a pure validation error raised before any store mutation, protecting the dependency graph from a degenerate 'duplicates' edge.","triggerScenarios":"`bd duplicate bd-42 --duplicate-of bd-42` or using the same prefix for both the positional argument and --duplicate-of where both resolve to the same issue.","commonSituations":"Copy-pasting the same ID into both arguments; scripting that interpolates the same variable twice; misunderstanding the command as 're-issue' rather than 'mark X as duplicate of Y'.","solutions":["Pass a different canonical issue in --duplicate-of than the issue being marked duplicate","Re-read the command semantics: bd duplicate <duplicate-id> --duplicate-of <canonical-id>","If the issue is genuinely not a duplicate, skip the command entirely"],"exampleFix":"// before\n$ bd duplicate bd-42 --duplicate-of bd-42\nError: cannot mark an issue as duplicate of itself\n// after\n$ bd duplicate bd-42 --duplicate-of bd-17","handlingStrategy":"validation","validationCode":"if dupID == canID {\n    return errors.New(\"duplicate and canonical must be different issues\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never reuse the same ID/prefix for both arguments","In scripts, assert the two variables differ before invoking bd duplicate"],"tags":["cli","validation","duplicate"],"backgroundTag":"self-referential-id-rejected","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}