gastownhall/beads · error

failed to close superseded issue: %w

Error message

failed to close superseded issue: %w

What it means

After the supersede edge is written, runSupersede closes the old issue through store.CloseIssue so the closure records the full lifecycle state. A failure here is wrapped with this message. The supersede dependency may already be persisted, so the state is partially applied: edge exists, old issue still open.

Source

Thrown at cmd/bd/duplicate.go:183

	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)
	}

	commandDidWrite.Store(true)

	if isJSONOutput() {
		return outputJSON(map[string]interface{}{
			"superseded":  oldID,
			"replacement": newID,
			"status":      "closed",
		})
	}

	fmt.Printf("%s Marked %s as superseded by %s (closed)\n", ui.RenderPass("✓"), oldID, newID)
	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the old issue state: if it is now closed and the supersedes edge exists, the supersede effectively completed — nothing to redo
  2. If the old issue is still open, re-run `bd supersede`; the dependency step tolerates re-application
  3. Inspect the wrapped cause with `bd doctor` for DB-level problems
  4. Use `bd update <oldID> --status closed` as a manual fallback if the lifecycle op keeps failing
Defensive patterns

Strategy: try-catch

Validate before calling

if st, err := getIssueStatus(oldID); err == nil && st == "closed" { /* already superseded/closed; skip */ }

Try / catch

if err := runSupersede(ctx, oldID, newID, actor); err != nil {
    if strings.Contains(err.Error(), "failed to close superseded issue") {
        // idempotent recovery: check status; close manually if still open
        _ = runBd("update", oldID, "--status", "closed")
    }
}

Prevention

When it happens

Trigger: CloseIssue on the old issue fails: store write error, the old issue was concurrently deleted or already closed by another actor, or the underlying Dolt transaction aborted.

Common situations: Two agents/users superseding the same issue concurrently; an automated job closed the old issue between the dependency write and the close; DB connectivity dropped mid-command.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/9d8cee4d5ff430b2. Report an issue: GitHub.