gastownhall/beads · error
failed to scan conflict: %w
Error message
failed to scan conflict: %w
What it means
Each row from dolt_conflicts is scanned into a tableConflict struct with two targets (`table`, num_conflicts). This error indicates rows.Scan failed — a column-count/type mismatch between what the engine returned and the two scan targets, or a value that cannot be decoded into the target Go types. rows.Err() afterwards would report iteration-level errors separately.
Source
Thrown at internal/storage/dolt/history.go:177
})
return result, err
}
// getInternalConflicts returns any merge conflicts in the current state (internal format).
// For the public interface, use GetConflicts which returns storage.Conflict.
func (s *DoltStore) getInternalConflicts(ctx context.Context) ([]*tableConflict, error) {
rows, err := s.queryContext(ctx,
"SELECT `table`, num_conflicts FROM dolt_conflicts")
if err != nil {
return nil, fmt.Errorf("failed to get conflicts: %w", err)
}
defer rows.Close()
var conflicts []*tableConflict
for rows.Next() {
var c tableConflict
if err := rows.Scan(&c.TableName, &c.NumConflicts); err != nil {
return nil, fmt.Errorf("failed to scan conflict: %w", err)
}
conflicts = append(conflicts, &c)
}
return conflicts, rows.Err()
}
// tableConflict represents a Dolt table-level merge conflict (internal representation).
type tableConflict struct {
TableName string
NumConflicts int
}
// ResolveConflicts resolves conflicts using the specified strategy
func (s *DoltStore) ResolveConflicts(ctx context.Context, table string, strategy string) error {
return versioncontrolops.ResolveConflicts(ctx, s.db, table, strategy)
}
View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped scan error for the offending column index and compare the engine's dolt_conflicts schema (SHOW CREATE TABLE) against the two expected columns.
- Match Dolt server and beads versions — upgrade beads or pin the Dolt engine version the release was tested against.
- Replace SELECT `table`, num_conflicts with an explicit column list matching the engine's actual schema if it has changed.
Example fix
// before
rows := s.queryContext(ctx, "SELECT `table`, num_conflicts FROM dolt_conflicts")
rows.Scan(&c.TableName, &c.NumConflicts) // fails if engine adds columns
// after
rows := s.queryContext(ctx, "SELECT `table`, num_conflicts FROM dolt_conflicts") // verify against SHOW CREATE TABLE dolt_conflicts
if err := rows.Scan(&c.TableName, &c.NumConflicts); err != nil {
return nil, fmt.Errorf("failed to scan conflict (check dolt engine version): %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
cols, err := db.Query("SHOW COLUMNS FROM dolt_conflicts")
// confirm the first columns are `table` and num_conflicts before scanning Try / catch
conflicts, err := store.GetConflicts(ctx)
if err != nil && strings.Contains(err.Error(), "failed to scan conflict") {
return fmt.Errorf("dolt_conflicts schema mismatch — check dolt engine version: %w", err)
} Prevention
- Pin Dolt engine versions in CI and deployments to avoid system-table schema drift.
- Check the engine's dolt_conflicts schema after any Dolt upgrade.
- Upgrade beads together with the storage engine, never independently.
When it happens
Trigger: The dolt_conflicts system table returns a different column set than expected (engine version changed the schema, e.g. extra conflict-detail columns), or a non-integer value lands in num_conflicts; also occurs if the driver returns NULL for a non-pointer scan target.
Common situations: Mixed Dolt server/client versions where the system table schema differs from what this beads build expects; connecting to a backend that emulates but does not exactly match Dolt's conflict table shape.
Related errors
- failed to scan history: %w
- ErrScan
- failed to get conflicts: %w
- query conflicts for table %s: %w
- conflict columns for table %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/42c1c07548a1d21f.
Report an issue: GitHub.