gastownhall/beads · error
check rename collision in %s: %w
Error message
check rename collision in %s: %w
What it means
Wrapped SQL failure from checkRenameTargetCollision: the probe that checks whether renaming a dependency target to newID would conflict with another target column on the same issue_id failed at the driver level. Unlike the deliberate collision error (3545), the query itself errored rather than finding a row. Table-not-exist is tolerated as no-op.
Source
Thrown at internal/storage/issueops/dependencies.go:898
query := fmt.Sprintf(`
SELECT 1 FROM %s a
JOIN %s b ON a.issue_id = b.issue_id
WHERE a.%s = ?
AND (b.%s = ? OR b.%s = ?)
LIMIT 1
`, table, table, typedCol, otherCols[0], otherCols[1])
var found int
err := tx.QueryRowContext(ctx, query, newID, newID, newID).Scan(&found)
if err == sql.ErrNoRows {
return nil
}
if err != nil {
if isTableNotExistError(err) {
return nil
}
return fmt.Errorf("check rename collision in %s: %w", table, err)
}
return fmt.Errorf("rename to %s collides with existing dependency target in %s", newID, table)
}
// RemoveDependencyInTx removes a dependency between two issues within an
// existing transaction. Automatically routes to wisp_dependencies if the
// source issue is an active wisp. When emitEvent is set and a row is actually
// removed it records a dependency_removed event (attributed to actor) on the
// source's event table; a no-op remove of a missing edge, or a structural remove
// with emitEvent unset, records nothing. Only the explicit bd dep remove verb
// sets emitEvent; structural removals (issue delete, reparent, batch, duplicate
// cleanup) leave it unset so they wire edges away silently, mirroring the
// proxied repository's DepInsertOpts.EmitEvent gate so both backends record
// identical history.
//
// It returns whether a dependency_removed event was actually written, so callers
// that stage tables for a Dolt commit stage the events table only when an event
// row exists (avoiding the sweep-unrelated-rows hazard doltAddAndCommit guardsView on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error; retry the rename transaction if it is transient (connection, timeout, lock).
- Verify schema completeness with migrations; both dependency tables need depends_on_issue_id, depends_on_wisp_id, depends_on_external.
- Confirm the DB user can SELECT from both dependency tables.
- Check server logs (Dolt/SQLite) for the underlying query failure.
Example fix
// before: rename fails on flaky connection
err := store.RenameIssue(ctx, oldID, newID)
// after: retry rename with backoff on transient DB errors
err = withRetry(3, func() error { return store.RenameIssue(ctx, oldID, newID) }) Defensive patterns
Strategy: retry
Validate before calling
// verify rename-probe prerequisites: table readable and expected columns present
for _, c := range []string{"depends_on_issue_id", "depends_on_wisp_id", "depends_on_external"} {
if err := db.QueryRow("SELECT " + c + " FROM dependencies LIMIT 1").Err(); err != nil {
return fmt.Errorf("dependencies.%s unavailable; migrate first: %w", c, err)
}
} Type guard
func isRenameProbeFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "check rename collision")
} Try / catch
err := store.RenameIssue(ctx, oldID, newID)
if isRenameProbeFailure(err) && isTransient(errors.Unwrap(err)) {
err = withBackoff(3, func() error { return store.RenameIssue(ctx, oldID, newID) })
} Prevention
- Retry whole rename transactions on transient driver errors.
- Keep schema migrations current so all three target columns exist.
- Set busy_timeout/lock waits appropriate to your concurrency level.
- Watch DB server logs for probe-query failures during rename windows.
When it happens
Trigger: Any caller (replaceDependencyTargetInTx, RetargetInboundDependenciesToWispInTx, RetargetInboundDependenciesToIssueInTx, UpdateIssueIDInDependencyTargetsInTx) runs the JOIN probe against dependencies or wisp_dependencies and gets a non-ErrNoRows driver error — connectivity loss, timeout, schema corruption, permission denial.
Common situations: Renaming an issue ID (bd mv / update --id) while the DB connection is flaky; Dolt server restart mid-rename; insufficient SELECT grants; a partially migrated schema missing typed target columns.
Related errors
- count inbound dependencies from %s: %w
- retarget inbound dependencies to wisp in %s for %s: %w
- retarget inbound dependencies to issue in %s for %s: %w
- check retarget collision in %s: %w
- lookup dependency type for %s -> %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/78d0f2455a0cd3bb.
Report an issue: GitHub.