gastownhall/beads · error

remove dependency: %w

Error message

remove dependency: %w

What it means

This error wraps the DELETE failure in removeDependencyInTx after the edge was positively located. The lookup succeeded (so the edge exists) but the DELETE FROM <depTable> WHERE issue_id=? AND <target>=? statement failed at the driver level, so the dependency was not removed and the whole transaction should roll back.

Source

Thrown at internal/storage/issueops/dependencies.go:944

	_, _, eventTable, depTable := WispTableRouting(isWisp)

	// Capture the row's type before deleting so we can dispatch the right
	// affected-set helper. If no row matches, treat as a no-op.
	var depType, depMetadata string
	row := tx.QueryRowContext(ctx, fmt.Sprintf(
		`SELECT type, metadata FROM %s WHERE issue_id = ? AND %s = ?`, depTable, DepTargetExpr),
		issueID, dependsOnID)
	if err := row.Scan(&depType, &depMetadata); err != nil {
		if errors.Is(err, sql.ErrNoRows) {
			return false, nil
		}
		return false, fmt.Errorf("lookup dependency type for %s -> %s: %w", issueID, dependsOnID, err)
	}

	if _, err := tx.ExecContext(ctx, fmt.Sprintf(
		`DELETE FROM %s WHERE issue_id = ? AND %s = ?`, depTable, DepTargetExpr),
		issueID, dependsOnID); err != nil {
		return false, fmt.Errorf("remove dependency: %w", err)
	}

	// The lookup above returned early when no row matched, so reaching here means
	// an edge was actually deleted. Record the dependency_removed event on the
	// source issue's event table for bd CLI / library history observers — but only
	// when emitEvent is set, so structural removes stay silent (parity with the
	// proxied repo and with the symmetric AddDependencyInTx EmitEvent gate).
	eventWritten := false
	if emitEvent {
		if err := RecordEventInTable(ctx, tx, eventTable, issueID, types.EventDependencyRemoved, actor,
			fmt.Sprintf("Removed dependency on %s", dependsOnID)); err != nil {
			return false, fmt.Errorf("record dependency_removed event: %w", err)
		}
		eventWritten = true
	}

	var affectedIssues, affectedWisps []string
	var aerr error

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped driver error: FK violation -> remove referencing rows; locked -> retry after the other writer finishes.
  2. Retry the whole removal transaction; dependency removal is idempotent (a second run sees no rows).
  3. Check for child rows/audit tables with FK references to the dependency edge and clear them.
  4. Verify you are connected to a writable primary, not a read-only replica.

Example fix

// before: delete blocked by FK
ok, err := store.RemoveDependencyInTx(ctx, tx, "bd-1", "bd-2", actor, true)
// after: remove referencing snapshot rows first, then retry
 tx.Exec("DELETE FROM dep_snapshots WHERE issue_id=? AND depends_on_id=?", "bd-1", "bd-2")
ok, err = store.RemoveDependencyInTx(ctx, tx, "bd-1", "bd-2", actor, true)
Defensive patterns

Strategy: retry

Validate before calling

// precheck: writable primary and no child FK rows blocking the delete
var count int
if err := db.QueryRow("SELECT COUNT(*) FROM dep_snapshots WHERE issue_id=? AND depends_on_id=?", issueID, dependsOnID).Scan(&count); err != nil {
    return err
}
if count > 0 { return fmt.Errorf("clear %d referencing rows first", count) }

Type guard

func isDepDeleteFailure(err error) bool {
    return err != nil && strings.Contains(err.Error(), "remove dependency:")
}

Try / catch

removed, err := store.RemoveDependency(ctx, issueID, dependsOnID, actor)
if isDepDeleteFailure(err) {
    if fkViolation(errors.Unwrap(err)) { return fmt.Errorf("clear referencing rows, then retry: %w", err) }
    if isTransient(errors.Unwrap(err)) { err = withBackoff(3, func() error { _, e := store.RemoveDependency(ctx, issueID, dependsOnID, actor); return e }) }
}

Prevention

When it happens

Trigger: RemoveDependencyInTx or ApplyParentPatch reaches the DELETE and the driver returns an error — FK RESTRICT from child rows, database locked by a concurrent writer, connection dropped, trigger rejection, or read-only replica.

Common situations: Concurrent CLI sessions contending for the SQLite write lock; FK constraints referencing the dependency row from audit tables; attempting writes against a read-only Dolt replica; disk-full during the delete.

Related errors


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