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
- Inspect the wrapped driver error to determine the root cause.
- Apply pending schema migrations so both dependency tables support depends_on_issue_id.
- Retry the promotion after resolving lock/availability issues; the transaction rollback leaves wisps intact.
- 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
- Never promote wisps against a database with pending migrations.
- Retry promotion transactions wholesale on transient errors; rollback leaves the wisp intact.
- Check server/DB availability before batch ephemeral promotion sweeps.
- Pin schema version checks into your deployment health checks.
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
- read dependencies for %s: %w
- copy dependency %s→%s: %w
- count inbound dependencies from %s: %w
- retarget inbound dependencies to wisp in %s for %s: %w
- check retarget collision in %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6245b170e1c6eb35.
Report an issue: GitHub.