gastownhall/beads · error
replacement issue not found: %s
Error message
replacement issue not found: %s
What it means
runSupersede resolves the replacement issue via store.GetIssue before wiring a supersedes dependency. When GetIssue returns an error or a nil issue, the command aborts so it never creates a supersede edge pointing at a nonexistent issue. This protects the dependency graph from dangling references.
Source
Thrown at cmd/bd/duplicate.go:167
var err error
oldID, err = utils.ResolvePartialID(ctx, store, args[0])
if err != nil {
return fmt.Errorf("failed to resolve %s: %w", args[0], err)
}
newID, err = utils.ResolvePartialID(ctx, store, supersededWith)
if err != nil {
return fmt.Errorf("failed to resolve %s: %w", supersededWith, err)
}
if oldID == newID {
return fmt.Errorf("cannot mark an issue as superseded by itself")
}
// Verify new issue exists
var newIssue *types.Issue
newIssue, err = store.GetIssue(ctx, newID)
if err != nil || newIssue == nil {
return fmt.Errorf("replacement issue not found: %s", newID)
}
// Add a "supersedes" dependency edge (old → new)
dep := &types.Dependency{
IssueID: oldID,
DependsOnID: newID,
Type: types.DepSupersedes,
}
if err := store.AddDependency(ctx, dep, actor); err != nil {
return fmt.Errorf("failed to add supersede link: %w", err)
}
// Close the superseded issue through the lifecycle operation so it records
// the complete closure state.
if err := store.CloseIssue(ctx, oldID, "", actor, ""); err != nil {
return fmt.Errorf("failed to close superseded issue: %w", err)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Verify the replacement ID with `bd show <newID>` before running supersede
- Run `bd dolt pull` / re-sync so the replacement issue exists locally
- Check you are in the repo/directory backed by the intended beads database
- Create the replacement issue first with `bd create` if it does not exist yet
Example fix
// before
newIssue, err = store.GetIssue(ctx, newID)
// after
// ensure the replacement exists (and surface the real storage error)
newIssue, err = store.GetIssue(ctx, newID)
if err != nil { return fmt.Errorf("lookup replacement %s: %w", newID, err) }
if newIssue == nil { return fmt.Errorf("replacement issue not found: %s (run `bd show %s` to verify)", newID, newID) } Defensive patterns
Strategy: validation
Validate before calling
// before supersede
if out, err := exec.Command("bd", "show", newID).CombinedOutput(); err != nil {
return fmt.Errorf("replacement %s does not exist: %s", newID, out)
} Try / catch
if err := runSupersede(ctx, oldID, newID); err != nil {
if strings.Contains(err.Error(), "replacement issue not found") {
// correct the ID / create the issue, then retry
}
} Prevention
- Copy issue IDs from `bd show`/`bd list` output instead of typing them
- Confirm both issues live in the same beads database before superseding
- Sync (`bd dolt pull`) before cross-session lifecycle operations
When it happens
Trigger: Running `bd supersede OLD NEW` where NEW does not exist in the store, NEW was deleted, the ID is misspelled or from another database, or GetIssue fails on a transient storage error (including err==nil with nil issue).
Common situations: Typo in the replacement issue ID; replacing across two separate beads databases; the replacement issue was closed-and-deleted by a cleanup/prune job; stale Dolt sync left the local DB without the issue.
Related errors
- cannot mark an issue as superseded by itself
- parent issue '%s' not found
- ErrAmbiguousID
- 'bd admin %s' is not yet supported in embedded mode
- cannot use multiple conflict resolution flags
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/db014f2189bdbc31.
Report an issue: GitHub.