{"record":{"id":"820988bd75feca6a","repo":"gastownhall/beads","slug":"query-dependency-sources-w","errorCode":null,"errorMessage":"query dependency sources: %w","messagePattern":"query dependency sources: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependencies.go","lineNumber":643,"sourceCode":"\tif err := rekeyDependencySourceInTx(ctx, tx, oldID, newID); err != nil {\n\t\treturn fmt.Errorf(\"rekey dependency sources %s -> %s: %w\", oldID, newID, err)\n\t}\n\treturn nil\n}\n\n// rekeyDependencySourceInTx rewrites dependencies.id for every edge whose source\n// issue was renamed to newID so the stored id equals depid.New(newID, target). It\n// matches rows by both newID (the normal post-FK-cascade state) and oldID (defensive,\n// in case a caller reaches here before the cascade) and re-asserts issue_id = newID\n// so the row converges either way. Only rows whose id is actually stale are touched.\nfunc rekeyDependencySourceInTx(ctx context.Context, tx *sql.Tx, oldID, newID string) error {\n\tqueryRows, err := tx.QueryContext(ctx, `\n\t\tSELECT id, depends_on_issue_id, depends_on_wisp_id, depends_on_external\n\t\tFROM dependencies\n\t\tWHERE issue_id = ? OR issue_id = ?\n\t`, newID, oldID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"query dependency sources: %w\", err)\n\t}\n\ttype rekey struct{ oldRowID, newRowID string }\n\tvar rekeys []rekey\n\tfor queryRows.Next() {\n\t\tvar id string\n\t\tvar issueTarget, wispTarget, external sql.NullString\n\t\tif err := queryRows.Scan(&id, &issueTarget, &wispTarget, &external); err != nil {\n\t\t\t_ = queryRows.Close()\n\t\t\treturn fmt.Errorf(\"scan dependency source: %w\", err)\n\t\t}\n\t\ttarget, ok := resolveDependencyTarget(issueTarget, wispTarget, external)\n\t\tif !ok {\n\t\t\tcontinue // ck_dep_one_target guarantees one target; skip defensively\n\t\t}\n\t\tif want := depid.New(newID, target); want != id {\n\t\t\trekeys = append(rekeys, rekey{oldRowID: id, newRowID: want})\n\t\t}\n\t}","sourceCodeStart":625,"sourceCodeEnd":661,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependencies.go#L625-L661","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Read the wrapped driver error after the colon for the root cause","Run schema migrations so dependencies has the expected columns (id, issue_id, depends_on_issue_id, depends_on_wisp_id, depends_on_external)","Check the database connection is alive; reconnect and retry the rename","If a previous statement in the same transaction failed, fix that root error first — the tx is already poisoned"],"exampleFix":"// before: querying against a stale schema\nSELECT id, issue_id, depends_on_issue_id, depends_on_wisp_id, depends_on_external FROM dependencies\n// Error: Unknown column 'depends_on_wisp_id'\n// after: migrate first\nbd migrate  # or bd doctor to check schema version","handlingStrategy":"try-catch","validationCode":"// Verify schema surface before rename\nvar colCount int\nerr := db.Get(&colCount, `SELECT COUNT(*) FROM information_schema.COLUMNS\n  WHERE TABLE_NAME='dependencies' AND COLUMN_NAME IN\n  ('id','issue_id','depends_on_issue_id','depends_on_wisp_id','depends_on_external')`)\nif err != nil || colCount < 5 {\n    return fmt.Errorf(\"dependencies schema out of date (found %d/5 columns); run bd migrate\", colCount)\n}","typeGuard":null,"tryCatchPattern":"err := updateIssueID(tx, oldID, newID)\nif err != nil {\n    if errors.Is(err, sql.ErrConnDone) || mysqlErrCode(err) == 2006 || mysqlErrCode(err) == 2013 {\n        // reconnect and retry; transaction rolled back atomically\n    }\n    return err\n}","preventionTips":["Run bd migrate after upgrading beads before mutating data","Ping the DB before long transactions; avoid renames over flaky connections","Never run statements on a transaction after an error — it is aborted","Verify the dependencies table exists with bd doctor before scripted bulk renames"],"tags":["database","sql","query","transaction"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}