{"record":{"id":"7f60ec3ee8d70b89","repo":"gastownhall/beads","slug":"query-conflicts-for-table-s-w","errorCode":null,"errorMessage":"query conflicts for table %s: %w","messagePattern":"query conflicts for table (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/versioncontrolops/automerge.go","lineNumber":100,"sourceCode":"\tourKey  any\n\tcolumns []string\n\tvalues  []any\n\t// lww names the cells both sides changed differently, which were settled\n\t// by timestamp rather than merged. They are the only cells where one\n\t// side's edit is superseded, so the resolver names them on stderr — the\n\t// same courtesy the config path pays for an otherwise-undiagnosable\n\t// supersession.\n\tlww []string\n}\n\n// loadConflictRows reads every live conflict row of table in raw scanned form.\nfunc loadConflictRows(ctx context.Context, db DBConn, table string) ([]rawConflictRow, 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\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})","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/versioncontrolops/automerge.go#L82-L118","documentation":"loadConflictRows queries the dolt_conflicts_<table> system table during auto-merge conflict inspection; this error wraps the QueryContext failure. The table name is validated as an identifier first, so the failure is almost always on the SQL/engine side, not injection-related. It propagates to callers deciding whether merge conflicts can be auto-resolved.","triggerScenarios":"TryAutoResolveMergeConflicts runs after a dolt merge with conflicts and `SELECT * FROM dolt_conflicts_issues` (or labels/comments/events) fails — no active conflict set (querying a conflicts table when no merge conflict exists), SQL syntax/engine error, or connection failure.","commonSituations":"Calling auto-resolve outside an active conflicted merge state; Dolt version where the conflicts system table is locked or unavailable; dropped connection to the Dolt server mid-resolution.","solutions":["Confirm a merge with conflicts is actually in progress (the conflicts table only exists/readable with live conflicts)","Read the wrapped cause for the real SQL error and fix it","Re-run or re-enter the merge so the conflict set is materialized, then retry auto-resolve","Check Dolt server connectivity and version compatibility"],"exampleFix":"// before: resolving without checking merge state\nerr := versioncontrolops.TryAutoResolveMergeConflicts(ctx, db)\n// after: only call when the merge left live conflicts\nif inConflictedMergeState(ctx, db) {\n    err = versioncontrolops.TryAutoResolveMergeConflicts(ctx, db)\n}","handlingStrategy":"type-guard","validationCode":"// Only attempt auto-resolve when a conflicted merge is actually live\nvar n int\nif err := db.QueryRowContext(ctx,\n    \"SELECT COUNT(*) FROM dolt_conflicts_issues\").Scan(&n); err != nil || n == 0 {\n    return fmt.Errorf(\"no live issues conflicts; skip auto-resolve\")\n}","typeGuard":"func hasLiveConflicts(ctx context.Context, db DBConn, table string) bool {\n    rows, err := db.QueryContext(ctx, \"SELECT 1 FROM `dolt_conflicts_`\"+table+\" LIMIT 1\")\n    if err != nil { _ = rows; return false }\n    defer rows.Close()\n    return rows.Next()\n}","tryCatchPattern":"err := versioncontrolops.TryAutoResolveMergeConflicts(ctx, db)\nif err != nil {\n    var merr *MergeConflictsError\n    if errors.As(err, nil) || strings.Contains(err.Error(), \"query conflicts for table\") {\n        // fall back to manual DOLT_CONFLICTS_RESOLVE --ours/--theirs\n    }\n    return err\n}","preventionTips":["Only invoke auto-resolve inside an active conflicted merge","Verify Dolt server connectivity before starting a merge","Keep dolt and beads versions compatible","Handle MergeConflictsError by surfacing tables to the operator for manual resolution"],"tags":["dolt","merge-conflicts","sql"],"backgroundTag":"dolt-conflict-table-read-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}