gastownhall/beads · error
query schema_migrations conflicts: %w
Error message
query schema_migrations conflicts: %w
What it means
This error comes from schemaMigrationsConflictsAreVintageOnly when the query against dolt_conflicts_schema_migrations fails. The function inspects every conflicted schema_migrations row to confirm all conflicts are 'vintage' (same version on both sides with equal or one-sided-empty content hashes) before the library auto-resolves them; if the query fails, the error is wrapped with 'query schema_migrations conflicts:' and auto-resolution is abandoned so the operator must resolve manually. Like its config counterpart, it is a wrapper over a driver-level failure.
Source
Thrown at internal/storage/versioncontrolops/mergesettle.go:724
keys = append(keys, key.String)
}
}
return keys, rows.Err()
}
// schemaMigrationsConflictsAreVintageOnly reports whether every conflicted
// schema_migrations row is the same migration version present on BOTH sides
// whose content hashes are compatible: equal, or NULL/empty on exactly one side
// (a pre-#4270 binary recorded the version without a hash, bd-6dnrw.29). Two
// different non-empty hashes mean the clones applied different content for the
// same version — the #4259 schema fork — and are never auto-resolved. A row
// deleted on one side is not a vintage artifact either.
func schemaMigrationsConflictsAreVintageOnly(ctx context.Context, db DBConn) (bool, error) {
rows, err := db.QueryContext(ctx, `
SELECT our_version, their_version, our_content_hash, their_content_hash
FROM dolt_conflicts_schema_migrations`)
if err != nil {
return false, fmt.Errorf("query schema_migrations conflicts: %w", err)
}
defer rows.Close()
for rows.Next() {
var ourVersion, theirVersion sql.NullInt64
var ourHash, theirHash sql.NullString
if err := rows.Scan(&ourVersion, &theirVersion, &ourHash, &theirHash); err != nil {
return false, fmt.Errorf("scan schema_migrations conflict: %w", err)
}
if !ourVersion.Valid || !theirVersion.Valid || ourVersion.Int64 != theirVersion.Int64 {
return false, nil
}
ours, theirs := ourHash.String, theirHash.String
if ours != "" && theirs != "" && ours != theirs {
return false, nil // real content skew (#4259) — operator decides
}
}
return true, rows.Err()View on GitHub (pinned to 71377f2769)
Solutions
- Confirm schema_migrations is actually in conflict (SHOW TABLES / dolt conflicts) — if the conflict table is absent on this Dolt version, upgrade Dolt or skip the pre-check.
- Retry the auto-resolve after verifying the Dolt database is reachable and no other process holds the database lock.
- Align bd and Dolt engine versions: a pre-#4270 binary's missing content_hash columns can make the conflict-table shape differ.
- If the query keeps failing, resolve schema_migrations conflicts manually (dolt conflicts resolve --ours schema_migrations) after verifying versions/hashes yourself.
- Check storage health with 'bd doctor' for embedded-mode issues.
Example fix
// before: unconditionally query the conflict table
rows, err := db.QueryContext(ctx, `
SELECT our_version, their_version, our_content_hash, their_content_hash
FROM dolt_conflicts_schema_migrations`)
if err != nil {
return false, fmt.Errorf("query schema_migrations conflicts: %w", err)
}
// after: treat 'table not found' as no conflicts
rows, err := db.QueryContext(ctx, `
SELECT our_version, their_version, our_content_hash, their_content_hash
FROM dolt_conflicts_schema_migrations`)
if err != nil {
if isNoSuchTableErr(err) {
return true, nil
}
return false, fmt.Errorf("query schema_migrations conflicts: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
// Preflight: confirm schema_migrations is actually conflicted and the
// conflict table is queryable before attempting vintage auto-resolution.
var n int
if err := db.QueryRowContext(ctx,
"SELECT COUNT(*) FROM dolt_conflicts_schema_migrations").Scan(&n); err != nil {
return fmt.Errorf("schema_migrations conflict preflight failed: %w", err)
} Try / catch
err := TryAutoResolveMergeConflicts(ctx, db)
if err != nil {
if strings.Contains(err.Error(), "query schema_migrations conflicts") {
// driver-level failure: reconnect or resolve manually with
// dolt conflicts resolve --ours schema_migrations
}
} Prevention
- Upgrade repos created by pre-#4270 binaries so schema_migrations carries content_hash consistently.
- Verify no other bd/dolt process holds the database lock before merging.
- Check DB reachability before starting merge or auto-resolve operations.
- Treat a missing dolt_conflicts_schema_migrations table as 'no conflicts', not a hard failure.
- Run 'bd doctor' after version upgrades to validate the storage layer.
When it happens
Trigger: TryAutoResolveMergeConflicts runs after a merge that conflicted on schema_migrations, and 'SELECT our_version, their_version, our_content_hash, their_content_hash FROM dolt_conflicts_schema_migrations' fails — the table doesn't exist (no such conflict class on this Dolt version or the table was already resolved), the connection/transaction is dead, or the driver returns an I/O/lock error.
Common situations: Dolt version drift: older binaries (pre-#4270) recorded schema_migrations without a content_hash column, so conflict tables on upgraded repos may mismatch expectations; repos where a previous resolve already cleared the conflict table; embedded Dolt connection failures or flocks held by another bd process; network loss against a remote Dolt server.
Related errors
- query config conflicts: %w
- scan schema_migrations conflict: %w
- failed to query cross-table duplicates: %w
- query cross-table duplicates: %w
- failed to get conflicts: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6e549548b6f89e51.
Report an issue: GitHub.