{"record":{"id":"9156e88baffe4d48","repo":"gastownhall/beads","slug":"iterate-conflicts-for-table-s-w","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/automerge.go","lineNumber":121,"sourceCode":"\n\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\tvar out []rawConflictRow\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, rawConflictRow{cols: cols, vals: 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// duplicateConflictKey reports the first our-side key held by more than one\n// live conflict row. Both resolvers settle a row by deleting its conflict BY\n// KEY, so two rows sharing one key would both be cleared by the first delete\n// and make the second iteration abort on \"no conflict row deleted\" — a message\n// about the wrong thing entirely, after a row was resolved without ever being\n// merged. loadConflictRow refuses the same shape on the operator's single-row\n// path (conflicts.go); the auto-merge pre-screens instead DECLINE on it, which\n// is this file's idiom and what lets the caller still build the\n// MergeConflictsError that tells an operator which tables need them.\n//\n// Rows whose our-side key is absent are skipped: a delete/modify conflict NULLs\n// our whole side, such a row is never the target of a keyed delete (the safety\n// checks decline it first), and treating several of them as one repeated key\n// would decline merges that are perfectly settleable.","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/automerge.go#L103-L139","documentation":"After iterating rows.Next() over dolt_conflicts_<table>, loadConflictRows checks rows.Err(); this wraps any iteration-level driver error. It catches errors that surfaced mid-iteration (e.g. connection dropped while streaming rows) which would otherwise be silently missed, ensuring a partial conflict read can never be treated as complete.","triggerScenarios":"Auto-merge resolution streams conflict rows and the connection or server fails mid-iteration — network drop, server restart, or query killed while reading dolt_conflicts rows.","commonSituations":"Remote Dolt server over flaky network; long-running resolution interrupted by server maintenance or timeout; OOM/killed query on huge conflict sets.","solutions":["Restore the connection/server and retry the merge auto-resolution","Reduce conflict volume by merging smaller, more frequent increments","Increase server query timeouts for large conflict sets"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"if err := db.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"connection unhealthy before conflict resolution: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := versioncontrolops.TryAutoResolveMergeConflicts(ctx, db)\nif err != nil && strings.Contains(err.Error(), \"iterate conflicts for table\") {\n    // stream broke mid-iteration: reconnect, re-enter merge state if\n    // needed, and retry the resolution from scratch\n    return retryAfterReconnect(ctx, db)\n}","preventionTips":["Resolve conflicts promptly after the merge, before connections idle out","Increase server query timeouts for large conflict sets","Merge in smaller increments to keep conflict sets small","Use wired/stable networking for remote Dolt servers during merges"],"tags":["dolt","merge-conflicts","network"],"backgroundTag":"database-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}