gastownhall/beads · error
canonical issue not found: %s
Error message
canonical issue not found: %s
What it means
Raised when store.GetIssue returns an error or nil for the resolved canonical ID in runDuplicate — the canonical issue could not be loaded from the store even though its ID resolved. This catches races (issue deleted between resolve and fetch) and storage read failures, and is reported with the canonical ID. The duplicate is left unmodified.
Source
Thrown at cmd/bd/duplicate.go:97
var err error
duplicateID, err = utils.ResolvePartialID(ctx, store, args[0])
if err != nil {
return fmt.Errorf("failed to resolve %s: %w", args[0], err)
}
canonicalID, err = utils.ResolvePartialID(ctx, store, duplicateOf)
if err != nil {
return fmt.Errorf("failed to resolve %s: %w", duplicateOf, err)
}
if duplicateID == canonicalID {
return fmt.Errorf("cannot mark an issue as duplicate of itself")
}
// Verify canonical issue exists
var canonical *types.Issue
canonical, err = store.GetIssue(ctx, canonicalID)
if err != nil || canonical == nil {
return fmt.Errorf("canonical issue not found: %s", canonicalID)
}
// Add a "duplicates" dependency edge (duplicate → canonical)
dep := &types.Dependency{
IssueID: duplicateID,
DependsOnID: canonicalID,
Type: types.DepDuplicates,
}
if err := store.AddDependency(ctx, dep, actor); err != nil {
return fmt.Errorf("failed to add duplicate link: %w", err)
}
// Close the duplicate issue through the lifecycle operation so it records
// the complete closure state.
if err := store.CloseIssue(ctx, duplicateID, "", actor, ""); err != nil {
return fmt.Errorf("failed to close duplicate: %w", err)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Re-run `bd show <canonical-id>` to check the issue still exists
- Re-run the duplicate command — a transient storage error may have cleared
- Run `bd doctor` / verify store integrity if GetIssue keeps failing
- Pick a different canonical issue if the target was deleted
Example fix
// before $ bd duplicate bd-42 --duplicate-of bd-99 # bd-99 deleted moments ago Error: canonical issue not found: bd-99 // after $ bd list | grep bd- # pick an existing canonical $ bd duplicate bd-42 --duplicate-of bd-101
Defensive patterns
Strategy: validation
Validate before calling
canonical, err := store.GetIssue(ctx, canonicalID)
if err != nil || canonical == nil {
return fmt.Errorf("canonical %s missing; pick another with bd list", canonicalID)
} Type guard
if canonical == nil {
return fmt.Errorf("canonical issue %s does not exist", canonicalID)
} Try / catch
canonical, err := store.GetIssue(ctx, canonicalID)
if err != nil {
if errors.Is(err, ErrKeyNotFound) { return fmt.Errorf("canonical %s deleted", canonicalID) }
return fmt.Errorf("storage error fetching canonical: %w", err)
} Prevention
- Re-verify the canonical issue immediately before marking duplicates
- Avoid deleting issues concurrently with duplicate-marking in multi-agent setups
When it happens
Trigger: The canonical issue was deleted or closed/purged between ResolvePartialID and GetIssue; the underlying Dolt/driver read fails; a nil row is returned for the resolved ID.
Common situations: Concurrent deletion by another agent or process in a multi-agent workflow; a stale replica out of sync; storage corruption or driver error surfacing as a GetIssue failure.
Related errors
- resolving ID %s: %w
- failed to check parent issue: %w
- failed to resolve %s: %w
- cannot mark an issue as duplicate of itself
- failed to add duplicate link: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/9deeb41a7ee8e8b5.
Report an issue: GitHub.