{"record":{"id":"6890605393cc8e0c","repo":"gastownhall/beads","slug":"iterate-conflicts-for-table-s-w-689060","errorCode":null,"errorMessage":"iterate conflicts for table %s: %w","messagePattern":"iterate conflicts for table (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/conflicts.go","lineNumber":144,"sourceCode":"\tcols, err := rows.Columns()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"conflict columns for table %s: %w\", table, err)\n\t}\n\n\tvar out []storage.ConflictRow\n\tfor rows.Next() {\n\t\tvals := make([]any, len(cols))\n\t\tptrs := make([]any, len(cols))\n\t\tfor i := range vals {\n\t\t\tptrs[i] = &vals[i]\n\t\t}\n\t\tif err := rows.Scan(ptrs...); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"scan conflict row for table %s: %w\", table, err)\n\t\t}\n\t\tout = append(out, buildConflictRow(table, cols, vals))\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn nil, fmt.Errorf(\"iterate conflicts for table %s: %w\", table, err)\n\t}\n\treturn out, nil\n}\n\n// buildConflictRow re-presents one raw conflict row as fields. It is pure, so\n// the column-splitting rules are unit-testable without a database.\nfunc buildConflictRow(table string, cols []string, vals []any) storage.ConflictRow {\n\trow := storage.ConflictRow{Table: table}\n\tindex := make(map[string]int, len(cols))\n\tfor i, col := range cols {\n\t\tside, field, ok := splitConflictColumn(col)\n\t\tif !ok {\n\t\t\tcontinue\n\t\t}\n\t\tv := formatConflictValue(vals[i])\n\t\tif conflictMetaSuffixes[field] {\n\t\t\tif field == \"diff_type\" && v != nil {\n\t\t\t\tswitch side {","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/conflicts.go#L126-L162","documentation":"GetConflictRows scanned all visible rows but rows.Err() returned an error during final iteration — meaning the row iterator hit a failure mid-stream (connection loss, server error, context cancellation) rather than completing normally. This is checked after the loop so partially collected data is discarded and the iteration failure is reported.","triggerScenarios":"The dolt connection drops or the query is aborted while GetConflictRows is iterating rows.Next(); context deadline exceeded mid-iteration; server-side kill of the running query.","commonSituations":"Long-running conflict scans over large conflicted tables hitting a context timeout; network instability between client and dolt sql-server; server restart during read.","solutions":["Inspect the wrapped error for cancellation vs connection loss","Increase the context timeout or re-run with a longer deadline","Retry on a fresh connection; conflicts data is read-only so retry is safe","Check dolt sql-server logs for query kills or restarts"],"exampleFix":"// before\nctx := context.Background()\n// after\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"var rows []storage.ConflictRow\nvar err error\nfor attempt := 0; attempt < 3; attempt++ {\n    rows, err = versioncontrolops.GetConflictRows(ctx, db, table)\n    if err == nil || !isTransient(err) { break }\n    time.Sleep(backoff(attempt))\n}","preventionTips":["Set generous context timeouts sized to table size","Read conflicts on a dedicated healthy connection","Treat iteration errors as safe-to-retry (read-only op)"],"tags":["database","dolt","sql","iteration"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}