gastownhall/beads · error

query config conflicts: %w

Error message

query config conflicts: %w

What it means

This error is returned by configConflictsAreMemoryConvergent when the SQL query against the dolt_conflicts_config system table fails. During a Dolt merge with unresolved conflicts, the library reads the conflict rows to decide whether all conflicted config keys are memory keys (safe to auto-resolve with --theirs); if the query itself errors, the error is wrapped with the 'query config conflicts:' prefix and bubbles up to TryAutoResolveMergeConflicts, aborting auto-resolution. It is a wrapper around the underlying database driver error, not a logic failure in the checker itself.

Source

Thrown at internal/storage/versioncontrolops/mergesettle.go:666

}

// configConflictsAreMemoryConvergent reports whether every conflicted config
// row is a persistent-memory row (key prefixed memoryConfigKeyPrefix). Memories
// are the only config class safe to auto-resolve with --theirs: like metadata,
// all clones pulling from the same remote converge on the remote's value (a
// local edit to the same memory key loses, the same convergent trade-off
// metadata makes). Any other config key in conflict — issue_prefix above all,
// whose stale-value sweep GH#2455 specifically guards against — is a real
// semantic conflict, so the whole config table is left for the operator.
//
// The key column is config's primary key, so a same-key conflict carries the
// identical key on both sides; an add/delete conflict leaves one side NULL. A
// row is convergent only if every key it presents is a memory key.
func configConflictsAreMemoryConvergent(ctx context.Context, db DBConn) (bool, error) {
	rows, err := db.QueryContext(ctx, `
		SELECT our_key, their_key FROM dolt_conflicts_config`)
	if err != nil {
		return false, fmt.Errorf("query config conflicts: %w", err)
	}
	defer rows.Close()

	for rows.Next() {
		var ourKey, theirKey sql.NullString
		if err := rows.Scan(&ourKey, &theirKey); err != nil {
			return false, fmt.Errorf("scan config conflict: %w", err)
		}
		for _, k := range []sql.NullString{ourKey, theirKey} {
			if k.Valid && !strings.HasPrefix(k.String, memoryConfigKeyPrefix) {
				return false, nil
			}
		}
	}
	return true, rows.Err()
}

// resolvedConfigConflictKeys returns the keys of the config rows currently in

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run the merge/resolve step again — transient driver or connection errors usually clear on retry once the Dolt database is reachable.
  2. Check that a merge actually left config conflicts: run 'CALL DOLT_CONFLICTS_RESOLVE' listing or query SHOW TABLES to confirm dolt_conflicts_config exists in this Dolt version.
  3. Verify the Dolt server/embedded engine version matches what this bd build expects; upgrade or downgrade so the dolt_conflicts_config system table is available.
  4. If the connection is dead, reopen the database (re-run bd open / restart the Dolt SQL server) before retrying the auto-resolve.
  5. If auto-resolution keeps failing, resolve conflicts manually (dolt conflicts resolve / bd resolve) so the pre-check is never needed.

Example fix

// before: query assumes the conflict table always exists
rows, err := db.QueryContext(ctx, `SELECT our_key, their_key FROM dolt_conflicts_config`)
if err != nil {
    return false, fmt.Errorf("query config conflicts: %w", err)
}
// after: tolerate a missing conflict table (no config conflicts) explicitly
rows, err := db.QueryContext(ctx, `SELECT our_key, their_key FROM dolt_conflicts_config`)
if err != nil {
    if isNoSuchTableErr(err) { // e.g. information_schema check or driver error code
        return true, nil // no config conflict rows -> trivially convergent
    }
    return false, fmt.Errorf("query config conflicts: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before invoking the auto-resolve, verify the repo is in a conflicted state
// and the conflict table is reachable:
var n int
err := db.QueryRowContext(ctx, "SELECT COUNT(*) FROM dolt_conflicts_config").Scan(&n)
if err != nil {
    // table missing or DB unreachable — resolve manually or reconnect first
    return fmt.Errorf("config conflict preflight failed: %w", err)
}

Try / catch

err := TryAutoResolveMergeConflicts(ctx, db)
var qErr *QueryConflictError // or errors.As on the wrapped driver error
if err != nil {
    if errors.Is(err, sql.ErrConnDone) || errors.Is(err, driver.ErrBadConn) {
        // reconnect and retry once
    } else {
        // fall back to manual conflict resolution
        log.Warn("auto-resolve skipped; resolve conflicts manually", "err", err)
    }
}

Prevention

When it happens

Trigger: Calling TryAutoResolveMergeConflicts (typically via bd's merge/pull version-control path) while the underlying Dolt database is in a conflicted state and the query 'SELECT our_key, their_key FROM dolt_conflicts_config' fails — e.g. the dolt_conflicts_config table does not exist (no config conflicts on the Dolt version in use, or schema drift between Dolt versions), the DB connection is broken/closed, the transaction was aborted, or the storage driver returns an I/O or lock error.

Common situations: Older or newer Dolt server versions that don't expose per-table dolt_conflicts_* tables the same way; running against a database that was never actually merged (table absent); an embedded Dolt connection that has been closed or hit a flock error; disk/IO failures mid-merge; mixing bd binary versions where the merge was performed by a different Dolt engine version.

Related errors


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