gastownhall/beads · warning

Failed to create dependency %s -> %s: %v

Error message

Failed to create dependency %s -> %s: %v

What it means

Both endpoints of the dependency resolved to local issues, but AddDependency failed when inserting the dependency edge into the store. The dependency is skipped and counted as failed; remaining dependencies are still processed. Common causes are uniqueness constraints (dependency already exists), foreign-key violations, or storage transaction errors.

Source

Thrown at internal/tracker/engine.go:1352

		}
		toIssue, err := resolveIssue(ctx, dep.ToExternalID)
		if err != nil {
			e.warn("Failed to resolve dependency target %s: %v", dep.ToExternalID, err)
			errCount++
			continue
		}

		if fromIssue == nil || toIssue == nil {
			continue // Not found (no error) — expected if issue wasn't imported
		}

		d := &types.Dependency{
			IssueID:     fromIssue.ID,
			DependsOnID: toIssue.ID,
			Type:        types.DependencyType(dep.Type),
		}
		if err := e.Store.AddDependency(ctx, d, e.Actor); err != nil {
			e.warn("Failed to create dependency %s -> %s: %v", fromIssue.ID, toIssue.ID, err)
			errCount++
		}
	}
	return errCount
}

func (e *Engine) previewDependencies(ctx context.Context, deps []DependencyInfo, dryRunIssues []*types.Issue) int {
	if len(deps) == 0 {
		return 0
	}

	resolveIssue, err := e.dependencyIssueResolver(ctx, dryRunIssues)
	if err != nil {
		e.warn("Failed to build dependency resolver: %v", err)
		return len(deps)
	}

	wouldCreate := 0

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check the wrapped error: 'unique constraint' means the dependency already exists — safe to ignore; 'foreign key' means an endpoint vanished — re-run pull.
  2. Re-run `bd pull` to retry failed edges; AddDependency is idempotent for existing edges.
  3. Normalize the tracker's dependency type strings to bd's supported types (blocks/related/blocks, etc.).
  4. Avoid concurrent bd processes writing during pull.
  5. If a constraint error persists, inspect and dedupe existing dependencies via `bd dep list`/storage queries.

Example fix

// before: tracker emits custom type "is-blocked-by"
Type: types.DependencyType(dep.Type) // "is-blocked-by" → insert error
// after: normalize in the tracker adapter's dependency mapper
switch dep.Type { case "is-blocked-by": return "blocks" (with endpoints swapped) }
Defensive patterns

Strategy: try-catch

Validate before calling

// skip known-duplicate edges before import
for _, dep := range deps {
    dup, _ := store.HasDependency(ctx, fromLocal(dep), toLocal(dep))
    if dup { log.Printf("edge exists, skipping: %v -> %v", dep.FromExternalID, dep.ToExternalID) }
}

Try / catch

// classify the failure: duplicates are safe, transient errors retry
stats, err := engine.Sync(ctx, opts)
if stats != nil && stats.FailedDeps > 0 {
    if isUniqueViolation(err) {
        log.Println("duplicate dependency edges — safe to ignore")
    } else if isTransient(err) {
        time.Sleep(backoff)
        engine.Sync(ctx, opts)
    }
}

Prevention

When it happens

Trigger: e.Store.AddDependency(ctx, d, e.Actor) returns an error — duplicate dependency edge (unique constraint), referenced issue deleted concurrently, invalid dependency type value, or storage lock/transaction failure.

Common situations: Tracker contains duplicate dependency links and the store enforces uniqueness; one endpoint was deleted by another process between resolution and insert; invalid dependency type string from the tracker not in bd's allowed set; DB lock during pull.

Related errors


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