{"record":{"id":"884dc78cece6bfc4","repo":"gastownhall/beads","slug":"conflict-columns-for-table-s-w-884dc7","errorCode":null,"errorMessage":"conflict columns for table %s: %w","messagePattern":"conflict columns for table (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/conflicts.go","lineNumber":128,"sourceCode":"}\n\n// GetConflictRows returns the live conflicted rows of table, one entry per\n// conflicted row with its columns presented per field. It reads the working\n// set: a merge whose conflicts were aborted (the auto-settle path) leaves\n// nothing here, which is correct — those conflicts no longer exist.\nfunc GetConflictRows(ctx context.Context, db DBConn, table string) ([]storage.ConflictRow, error) {\n\tif err := ValidateConflictTable(table); err != nil {\n\t\treturn nil, err\n\t}\n\trows, err := db.QueryContext(ctx, \"SELECT * FROM `dolt_conflicts_\"+table+\"`\") //nolint:gosec // table validated as an identifier above\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"query conflicts for table %s: %w\", table, err)\n\t}\n\tdefer func() { _ = rows.Close() }()\n\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\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","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/conflicts.go#L110-L146","documentation":"GetConflictRows executed the conflict query but failed to retrieve the result-set column metadata from the dolt_conflicts_<table> table via rows.Columns(). This is a driver-level failure reading column descriptors after a successful query, wrapped with the table name for context.","triggerScenarios":"Calling GetConflictRows when the rows object returned by QueryContext is invalidated before Columns() is called — e.g. the underlying connection was closed between the query and the Columns() call, a driver desync occurred, or the statement errored server-side mid-metadata exchange.","commonSituations":"Flaky/unstable database connections (network drop, dolt server restart) between QueryContext and Columns; driver bugs on large or unusual result sets; context cancelled concurrently.","solutions":["Inspect the wrapped driver error for connection issues","Retry the operation on a fresh connection/session","Ensure the context is not cancelled between query and column read","Check the dolt driver version for known metadata bugs"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"rows, err := versioncontrolops.GetConflictRows(ctx, db, table)\nif err != nil {\n    if errors.Is(err, driver.ErrBadConn) {\n        rows, err = versioncontrolops.GetConflictRows(ctx, db, table) // retry on fresh conn\n    }\n    if err != nil { return err }\n}","preventionTips":["Use connection pools that transparently retry ErrBadConn","Avoid cancelling contexts mid-read","Monitor network stability to the dolt sql-server"],"tags":["database","dolt","sql","resultset"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}