gastownhall/beads · error

query dependency sources: %w

Error message

query dependency sources: %w

What it means

This error wraps the failure of the SELECT that finds dependency edges whose source issue_id is either newID (normal post-cascade state) or oldID (defensive) inside rekeyDependencySourceInTx. It means the SQL query itself failed against the dependencies table within the active transaction — not a data or logic problem downstream.

Source

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

	if err := rekeyDependencySourceInTx(ctx, tx, oldID, newID); err != nil {
		return fmt.Errorf("rekey dependency sources %s -> %s: %w", oldID, newID, err)
	}
	return nil
}

// rekeyDependencySourceInTx rewrites dependencies.id for every edge whose source
// issue was renamed to newID so the stored id equals depid.New(newID, target). It
// matches rows by both newID (the normal post-FK-cascade state) and oldID (defensive,
// in case a caller reaches here before the cascade) and re-asserts issue_id = newID
// so the row converges either way. Only rows whose id is actually stale are touched.
func rekeyDependencySourceInTx(ctx context.Context, tx *sql.Tx, oldID, newID string) error {
	queryRows, err := tx.QueryContext(ctx, `
		SELECT id, depends_on_issue_id, depends_on_wisp_id, depends_on_external
		FROM dependencies
		WHERE issue_id = ? OR issue_id = ?
	`, newID, oldID)
	if err != nil {
		return fmt.Errorf("query dependency sources: %w", err)
	}
	type rekey struct{ oldRowID, newRowID string }
	var rekeys []rekey
	for queryRows.Next() {
		var id string
		var issueTarget, wispTarget, external sql.NullString
		if err := queryRows.Scan(&id, &issueTarget, &wispTarget, &external); err != nil {
			_ = queryRows.Close()
			return fmt.Errorf("scan dependency source: %w", err)
		}
		target, ok := resolveDependencyTarget(issueTarget, wispTarget, external)
		if !ok {
			continue // ck_dep_one_target guarantees one target; skip defensively
		}
		if want := depid.New(newID, target); want != id {
			rekeys = append(rekeys, rekey{oldRowID: id, newRowID: want})
		}
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped driver error after the colon for the root cause
  2. Run schema migrations so dependencies has the expected columns (id, issue_id, depends_on_issue_id, depends_on_wisp_id, depends_on_external)
  3. Check the database connection is alive; reconnect and retry the rename
  4. If a previous statement in the same transaction failed, fix that root error first — the tx is already poisoned

Example fix

// before: querying against a stale schema
SELECT id, issue_id, depends_on_issue_id, depends_on_wisp_id, depends_on_external FROM dependencies
// Error: Unknown column 'depends_on_wisp_id'
// after: migrate first
bd migrate  # or bd doctor to check schema version
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify schema surface before rename
var colCount int
err := db.Get(&colCount, `SELECT COUNT(*) FROM information_schema.COLUMNS
  WHERE TABLE_NAME='dependencies' AND COLUMN_NAME IN
  ('id','issue_id','depends_on_issue_id','depends_on_wisp_id','depends_on_external')`)
if err != nil || colCount < 5 {
    return fmt.Errorf("dependencies schema out of date (found %d/5 columns); run bd migrate", colCount)
}

Try / catch

err := updateIssueID(tx, oldID, newID)
if err != nil {
    if errors.Is(err, sql.ErrConnDone) || mysqlErrCode(err) == 2006 || mysqlErrCode(err) == 2013 {
        // reconnect and retry; transaction rolled back atomically
    }
    return err
}

Prevention

When it happens

Trigger: UpdateIssueIDInTx -> UpdateIssueIDInDependenciesInTx -> rekeyDependencySourceInTx, when tx.QueryContext on `dependencies WHERE issue_id = ? OR issue_id = ?` returns a driver error: table missing, schema mismatch, connection dropped, or transaction already aborted by a prior error.

Common situations: Running an older database schema lacking the dependencies table or its columns (depends_on_wisp_id, depends_on_external); connection lost mid-transaction; a prior statement in the same tx failed and the driver rejects further queries.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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