{"record":{"id":"87cc53a3a742bfb7","repo":"gastownhall/beads","slug":"scan-dependency-source-w","errorCode":null,"errorMessage":"scan dependency source: %w","messagePattern":"scan dependency source: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/dependencies.go","lineNumber":652,"sourceCode":"// 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}\n\t_ = queryRows.Close()\n\tif err := queryRows.Err(); err != nil {\n\t\treturn fmt.Errorf(\"iterate dependency sources: %w\", err)\n\t}\n\tfor _, rk := range rekeys {\n\t\tif _, err := tx.ExecContext(ctx,\n\t\t\t\"UPDATE dependencies SET id = ?, issue_id = ? WHERE id = ?\",\n\t\t\trk.newRowID, newID, rk.oldRowID); err != nil {\n\t\t\treturn fmt.Errorf(\"rekey dependency source id %s -> %s: %w\", rk.oldRowID, rk.newRowID, err)","sourceCodeStart":634,"sourceCodeEnd":670,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/dependencies.go#L634-L670","documentation":"This error wraps a rows.Scan failure while reading a dependency source row (id plus the three nullable target columns) in rekeyDependencySourceInTx. Scan fails when the stored value's type does not match the scan destination (e.g. non-string id, corrupt NULL in a NOT NULL column) or the column count mismatches the schema.","triggerScenarios":"During UpdateIssueIDInTx, a row in dependencies matching issue_id = oldID OR issue_id = newID has a value that cannot be scanned into string or sql.NullString — typically corrupt or schema-divergent data.","commonSituations":"Database written by an incompatible older/newer beads version; manual SQL edits that changed column types; Dolt replication divergence producing malformed rows.","solutions":["Read the wrapped scan error to see which column/type mismatched","Run bd doctor to detect and repair schema/data inconsistencies","Dump and inspect the offending dependencies row: SELECT * FROM dependencies WHERE issue_id IN (oldID, newID)","Restore the row from a backup or delete/recreate the malformed dependency edge"],"exampleFix":"// before: corrupt row breaks rename\ndefault_params: id column holds an integer where a string is expected -> scan dependency source: sql: Scan error\n// after: repair the row\nUPDATE dependencies SET id = CAST(id AS CHAR) WHERE id REGEXP '^[0-9]+$';  -- or restore from backup","handlingStrategy":"validation","validationCode":"// Detect rows that cannot be scanned into the expected types\nvar bad int\nerr := db.Get(&bad, `SELECT COUNT(*) FROM dependencies\n  WHERE id IS NULL OR id = ''\n     OR (depends_on_issue_id IS NULL AND depends_on_wisp_id IS NULL AND depends_on_external IS NULL)`)\nif err != nil { return err }\nif bad > 0 { return fmt.Errorf(\"%d malformed dependency rows; run bd doctor before renaming issues\", bad) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never hand-edit the dependencies table with raw SQL","Run bd doctor after version upgrades or clone/merge operations","Restore corrupt rows from backup before attempting renames","Keep all replicas in sync; scan mismatches often indicate replication divergence"],"tags":["database","scan","data-corruption","sql"],"backgroundTag":"sql-scan-type-mismatch","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}