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

  1. 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.
  2. Match Dolt server and beads versions — upgrade beads or pin the Dolt engine version the release was tested against.
  3. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/42c1c07548a1d21f. Report an issue: GitHub.