gastownhall/beads · error
scan conflict row for table %s: %w
Error message
scan conflict row for table %s: %w
What it means
loadConflictRows scans each conflict row into generic []any pointers; this error wraps a rows.Scan failure for a specific table. Scanning fails when a column's value cannot be converted into a generic any slot — typically NULL-shape or type issues in the conflict row produced by dolt, or column-count mismatch when a peer's schema merge changed the conflicts table shape.
Source
Thrown at internal/storage/versioncontrolops/automerge.go:116
rows, err := db.QueryContext(ctx, "SELECT * FROM `dolt_conflicts_"+table+"`") //nolint:gosec // table validated as an identifier above
if err != nil {
return nil, fmt.Errorf("query conflicts for table %s: %w", table, err)
}
defer func() { _ = rows.Close() }()
cols, err := rows.Columns()
if err != nil {
return nil, fmt.Errorf("conflict columns for table %s: %w", table, err)
}
var out []rawConflictRow
for rows.Next() {
vals := make([]any, len(cols))
ptrs := make([]any, len(cols))
for i := range vals {
ptrs[i] = &vals[i]
}
if err := rows.Scan(ptrs...); err != nil {
return nil, fmt.Errorf("scan conflict row for table %s: %w", table, err)
}
out = append(out, rawConflictRow{cols: cols, vals: vals})
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("iterate conflicts for table %s: %w", table, err)
}
return out, nil
}
// duplicateConflictKey reports the first our-side key held by more than one
// live conflict row. Both resolvers settle a row by deleting its conflict BY
// KEY, so two rows sharing one key would both be cleared by the first delete
// and make the second iteration abort on "no conflict row deleted" — a message
// about the wrong thing entirely, after a row was resolved without ever being
// merged. loadConflictRow refuses the same shape on the operator's single-row
// path (conflicts.go); the auto-merge pre-screens instead DECLINE on it, which
// is this file's idiom and what lets the caller still build the
// MergeConflictsError that tells an operator which tables need them.View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause to see which column/type failed to scan
- Abort and resolve the merge manually with dolt's table-level resolution (DOLT_CONFLICTS_RESOLVE --ours/--theirs), then retry
- Align both branches' schemas before merging so conflict rows keep the expected shape
- Upgrade dolt/beads if the conflict-row format changed between versions
Defensive patterns
Strategy: fallback
Validate before calling
// Check the conflict table's column count matches the base table's
// expected shape before auto-resolve
rows, _ := db.QueryContext(ctx, "SELECT * FROM dolt_conflicts_issues LIMIT 1")
cols, _ := rows.Columns()
rows.Close()
if len(cols) < expectedMinConflictColumns { /* shape drifted; use manual resolution */ } Try / catch
err := versioncontrolops.TryAutoResolveMergeConflicts(ctx, db)
if err != nil && strings.Contains(err.Error(), "scan conflict row for table") {
// conflict-row shape unexpected (schema merge): fall back to
// manual table-level resolution
return manualResolve(ctx, db)
} Prevention
- Keep both branches' schemas identical before merging
- Apply schema changes on one side at a time and merge promptly
- Avoid third-party tools writing arbitrary columns into the issues table
- Pin compatible dolt versions across collaborators
When it happens
Trigger: Auto-resolve reads dolt_conflicts_issues (or labels/comments/events) and a row cannot be scanned — a peer's schema merge extended the conflict table's columns so the scan buffer mismatches, or the conflict row contains a value type the driver will not scan into any.
Common situations: Merging branches where the schema itself changed (new columns) so dolt_conflicts tables carry extra base/our/their metadata; corrupted conflict rows after a crash.
Related errors
- clone from %s succeeded, but the database needs %d schema %s
- failed to recompute is_blocked: %w
- failed to count issues: %w
- failed to scan comment: %w
- failed to get conflicts: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/848e555f6276221e.
Report an issue: GitHub.