gastownhall/beads · error

conflict for %s %s carries no their_* data columns

Error message

conflict for %s %s carries no their_* data columns

What it means

When applying the 'theirs' strategy, resolveOneConflictRow collects their_* data columns from the conflict row to write back into the base table; none were found. This means the conflict row carries no transferable their-side data beyond metadata and the key, so there is nothing to apply. Usually indicates an unexpected conflict-table shape or an empty their-side payload.

Source

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

// matters, since the delete is what tells dolt the row is settled.
func resolveOneConflictRow(ctx context.Context, db DBConn, table, keyCol, key, strategy string, row rawConflictRow) error {
	ourKey, ourOK := row.value("our", keyCol)
	theirKey, theirOK := row.value("their", keyCol)
	if !ourOK || !theirOK {
		return fmt.Errorf("conflict table dolt_conflicts_%s has no our_%s/their_%s column", table, keyCol, keyCol)
	}
	if ourKey == nil || theirKey == nil {
		// delete/modify (one side removed the row) or add/add against a
		// missing key: refuse by name. Row-level ours/theirs would silently
		// resurrect or destroy a row the operator never looked at.
		return fmt.Errorf("conflict for %s %s is not a modify/modify conflict (one side has no row); "+
			"resolve it with a whole-table strategy or edit the row directly", table, key)
	}

	if strategy == ConflictStrategyTheirs {
		names, vals := row.theirFields(keyCol)
		if len(names) == 0 {
			return fmt.Errorf("conflict for %s %s carries no their_* data columns", table, key)
		}
		sets := make([]string, len(names))
		args := make([]any, 0, len(names)+1)
		for i, n := range names {
			// Column names are interpolated (MySQL cannot bind an
			// identifier) and come from the conflict table's own schema,
			// which a peer's schema merge can extend — gate them exactly
			// like the table name rather than trusting the source.
			if err := ValidateConflictTable(n); err != nil {
				return fmt.Errorf("refusing to write unexpected column %q of %s: %w", n, table, err)
			}
			sets[i] = fmt.Sprintf("`%s` = ?", n)
			args = append(args, vals[i])
		}
		args = append(args, ourKey)
		stmt := fmt.Sprintf("UPDATE `%s` SET %s WHERE `%s` = ?", table, strings.Join(sets, ", "), keyCol) //nolint:gosec // identifiers validated above
		res, err := db.ExecContext(ctx, stmt, args...)
		if err != nil {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect `SELECT * FROM dolt_conflicts_<table>` to see what their_* columns actually exist
  2. Check the dolt version; align peers on a version whose conflict-table layout matches this library's expectations
  3. Fall back to whole-table --theirs resolution, which rebuilds rows from the branch rather than the conflict row
  4. Abort and redo the merge if the conflict table looks structurally corrupted

Example fix

null
Defensive patterns

Strategy: validation

Validate before calling

// verify the conflict row carries their_* data columns before theirs strategy
cols, _ := conflictTableColumns(ctx, db, table)
hasData := false
for _, c := range cols {
    if strings.HasPrefix(c, "their_") && !isMetaOrKey(c, keyCol) { hasData = true }
}
if !hasData && strategy == "theirs" { return resolveWholeTable(ctx, db, table, "theirs") }

Try / catch

err := resolveOne(ctx, db, table, keyCol, key, "theirs")
if err != nil && strings.Contains(err.Error(), "carries no their_* data columns") {
    return resolveWholeTable(ctx, db, table, "theirs")
}
return err

Prevention

When it happens

Trigger: ResolveConflictRows -> resolveOneConflictRow with strategy == theirs calls row.theirFields(keyCol), which filters out our_*, metadata-suffixed columns and the key column; the result is empty, e.g. when the conflict table has only key/metadata columns or column naming deviates from the base_<col>/their_<col> convention.

Common situations: Dolt version whose conflict-table metadata columns are not in the expected suffix set; conflicts created against a table whose data columns were all dropped in a schema merge; manually constructed conflict rows.

Related errors


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