gastownhall/beads · error

failed to add duplicate link: %w

Error message

failed to add duplicate link: %w

What it means

Wraps store.AddDependency failure when creating the 'duplicates' dependency edge (duplicate → canonical) in runDuplicate. The store refused or failed to persist the dependency — storage-level error, constraint violation, or a driver write failure. The duplicate issue is NOT closed in this case because the command aborts before CloseIssue.

Source

Thrown at cmd/bd/duplicate.go:107

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

	commandDidWrite.Store(true)

	if isJSONOutput() {
		return outputJSON(map[string]interface{}{
			"duplicate": duplicateID,
			"canonical": canonicalID,
			"status":    "closed",
		})
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the command — transient write failures often clear on retry
  2. Check storage health (disk space, DB lock, `bd doctor`)
  3. Inspect existing dependencies (`bd dep <id>`) and remove a conflicting edge if present
  4. Verify you are not writing to a read-only store/replica

Example fix

// before
$ bd duplicate bd-42 --duplicate-of bd-17  # disk full
Error: failed to add duplicate link: disk I/O error
// after
$ df -h && rm -rf /tmp/cache && bd duplicate bd-42 --duplicate-of bd-17
Defensive patterns

Strategy: retry

Validate before calling

// pre-check storage writability and existing deps
if _, err := store.GetIssue(ctx, canonicalID); err != nil { return err }
if err := diskHasSpace(); err != nil { return err }

Try / catch

err := store.AddDependency(ctx, dep, actor)
for i := 0; i < 3 && err != nil; i++ {
    time.Sleep(backoff(i))
    err = store.AddDependency(ctx, dep, actor)
}
if err != nil { return fmt.Errorf("failed to add duplicate link: %w", err) }

Prevention

When it happens

Trigger: AddDependency returns an error: storage write failure, dependency validation (e.g. circular/self dependency rejected downstream), duplicate edge conflicts, or driver/DB errors from the Dolt backend.

Common situations: Database locked or out of disk space during a write; corrupted store; driver-level constraint triggered by an unexpected pre-existing dependency; running against a read-only replica.

Related errors


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