gastownhall/beads · error

retarget inbound dependencies to issue in %s for %s: %w

Error message

retarget inbound dependencies to issue in %s for %s: %w

What it means

This error wraps a SQL failure from the UPDATE that rewrites inbound dependency edges pointing at a wisp (depends_on_wisp_id = id) so they point at a regular issue (depends_on_issue_id = id) during a wisp-to-issue promotion. It is thrown by RetargetInboundDependenciesToIssueInTx, which runs the UPDATE on both dependencies and wisp_dependencies tables within the caller's transaction. The wrapped error is the underlying driver error.

Source

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

		}
	}
	return nil
}

func RetargetInboundDependenciesToIssueInTx(ctx context.Context, tx DBTX, id string) error {
	for _, table := range []string{"dependencies", "wisp_dependencies"} {
		if err := checkRetargetTargetCollision(ctx, tx, table, "depends_on_wisp_id", "depends_on_issue_id", id); err != nil {
			return err
		}
		if err := checkRenameTargetCollision(ctx, tx, table, "depends_on_issue_id", id); err != nil {
			return err
		}
		if _, err := tx.ExecContext(ctx, fmt.Sprintf(`
			UPDATE %s
			SET depends_on_issue_id = ?, depends_on_wisp_id = NULL
			WHERE depends_on_wisp_id = ?
		`, table), id, id); err != nil {
			return fmt.Errorf("retarget inbound dependencies to issue in %s for %s: %w", table, id, err)
		}
	}
	return nil
}

// UpdateIssueIDInDependencyTargetsInTx is called after the issues PK is updated
// from oldID to newID. FK ON UPDATE CASCADE has already propagated
// depends_on_issue_id from oldID to newID across dependencies and
// wisp_dependencies, so no rewrite is needed.
func UpdateIssueIDInDependencyTargetsInTx(ctx context.Context, tx *sql.Tx, _, newID string) error {
	for _, table := range []string{"dependencies", "wisp_dependencies"} {
		if err := checkRenameTargetCollision(ctx, tx, table, "depends_on_issue_id", newID); err != nil {
			return err
		}
	}
	return nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error to determine the root cause.
  2. Apply pending schema migrations so both dependency tables support depends_on_issue_id.
  3. Retry the promotion after resolving lock/availability issues; the transaction rollback leaves wisps intact.
  4. If constraints block the rewrite, delete or remap the offending dependency rows first, then rerun.

Example fix

// before: promotion fails with 'no such column: depends_on_issue_id'
err := PromoteFromEphemeralInTx(ctx, tx, wispID)
// after: check schema version first
if !store.SchemaSupportsTypedDependencyTargets() { return fmt.Errorf("run bd migrate first") }
err := PromoteFromEphemeralInTx(ctx, tx, wispID)
Defensive patterns

Strategy: try-catch

Validate before calling

// verify both dependency tables can target issues before promoting a wisp
for _, t := range []string{"dependencies", "wisp_dependencies"} {
    if err := db.QueryRow(fmt.Sprintf("SELECT depends_on_issue_id FROM %s LIMIT 1", t)).Err(); err != nil {
        return fmt.Errorf("%s missing typed column; migrate first: %w", t, err)
    }
}

Type guard

func isRetargetToIssueErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "retarget inbound dependencies to issue")
}

Try / catch

err := store.PromoteFromEphemeral(ctx, wispID)
if err != nil {
    if isTransientDBError(errors.Unwrap(err)) {
        return retryTx(func(tx *sql.Tx) error { return store.PromoteFromEphemeralInTx(ctx, tx, wispID) })
    }
    return err
}

Prevention

When it happens

Trigger: Calling MoveIssuePersistenceInTx (wisp rename/move) or PromoteFromEphemeralInTx when the UPDATE statement fails — missing depends_on_issue_id column in an unmigrated schema, connection loss, constraint rejection, or an already-aborted transaction.

Common situations: Promoting an ephemeral/wisp issue to a permanent issue on an out-of-date database schema; a crashed or locked Dolt/SQLite backend during promotion; partially applied migrations that created wisp_dependencies but not the typed issue-target column.

Related errors


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