gastownhall/beads · error

scan conflict row for table %s: %w

Error message

scan conflict row for table %s: %w

What it means

GetConflictRows read column metadata fine but failed while scanning one conflict row into the value buffers. rows.Scan returns an error when the number of destination pointers does not match the column count or when a value's type cannot be converted into the destination. The library allocates one generic any pointer per column, so this usually signals a driver scan/convert failure.

Source

Thrown at internal/storage/versioncontrolops/conflicts.go:139

	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 []storage.ConflictRow
	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, buildConflictRow(table, cols, vals))
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("iterate conflicts for table %s: %w", table, err)
	}
	return out, nil
}

// buildConflictRow re-presents one raw conflict row as fields. It is pure, so
// the column-splitting rules are unit-testable without a database.
func buildConflictRow(table string, cols []string, vals []any) storage.ConflictRow {
	row := storage.ConflictRow{Table: table}
	index := make(map[string]int, len(cols))
	for i, col := range cols {
		side, field, ok := splitConflictColumn(col)
		if !ok {
			continue

View on GitHub (pinned to 71377f2769)

Solutions

  1. Re-run the query after ensuring no concurrent schema changes are happening
  2. Check the wrapped error for which column failed to convert
  3. Verify the dolt server and driver versions match
  4. Re-trigger the merge to regenerate clean conflict rows if they appear corrupted
Defensive patterns

Strategy: try-catch

Try / catch

rows, err := versioncontrolops.GetConflictRows(ctx, db, table)
if err != nil {
    if strings.Contains(err.Error(), "scan conflict row") {
        return fmt.Errorf("conflict schema changed; re-run merge: %w", err) // schema drift: don't blind-retry
    }
    return err
}

Prevention

When it happens

Trigger: A conflict row contains a value the driver cannot scan into *any (rare) or the number of columns changed between Columns() and Scan (schema drift, concurrent DDL); nil handling or driver-level conversion errors on unusual column types.

Common situations: Schema of the user table changed while conflicts were being read; dolt version mismatch producing unexpected system-column types in dolt_conflicts_<table>; corrupted or partially-written conflict rows after a crash.

Related errors


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