gastownhall/beads · error

backfill content_hash for migration %d: %w

Error message

backfill content_hash for migration %d: %w

What it means

After computing fixes for schema_migrations conflict rows, this code backfills the missing content_hash column by UPDATE-ing each conflicted version with the winning hash. If the UPDATE fails (connection error, lock conflict, engine error), it is wrapped in this message. It indicates the auto-resolve could not normalize the migration table before calling DOLT_CONFLICTS_RESOLVE.

Source

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

	for rows.Next() {
		var version sql.NullInt64
		var ourHash, theirHash sql.NullString
		if err := rows.Scan(&version, &ourHash, &theirHash); err != nil {
			_ = rows.Close()
			return fmt.Errorf("scan schema_migrations conflict: %w", err)
		}
		if ourHash.String == "" && theirHash.String != "" {
			fixes = append(fixes, hashFix{version: version.Int64, hash: theirHash.String})
		}
	}
	if err := errors.Join(rows.Err(), rows.Close()); err != nil {
		return err
	}

	for _, f := range fixes {
		if _, err := db.ExecContext(ctx,
			"UPDATE schema_migrations SET content_hash = ? WHERE version = ?", f.hash, f.version); err != nil {
			return fmt.Errorf("backfill content_hash for migration %d: %w", f.version, err)
		}
	}
	if _, err := db.ExecContext(ctx, "CALL DOLT_CONFLICTS_RESOLVE('--ours', 'schema_migrations')"); err != nil {
		return fmt.Errorf("failed to resolve schema_migrations conflicts: %w", err)
	}
	return nil
}

// resolveConflictDepTarget returns the single non-null dependency target from a
// conflict row's three typed target columns, following the same precedence as
// COALESCE(depends_on_issue_id, depends_on_wisp_id, depends_on_external).
func resolveConflictDepTarget(issueTarget, wispTarget, external sql.NullString) (string, bool) {
	switch {
	case issueTarget.Valid:
		return issueTarget.String, true
	case wispTarget.Valid:
		return wispTarget.String, true
	case external.Valid:

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error for the real cause (unknown column, lock wait timeout, etc.).
  2. Verify schema_migrations has a content_hash column: SHOW CREATE TABLE schema_migrations.
  3. Retry the merge after ensuring no other bd/dolt process holds a write transaction on the database.
  4. If content_hash is missing on one side, reconcile the migration table schema first, then re-run the merge.

Example fix

// before: silent failure path
UPDATE schema_migrations SET content_hash = ? WHERE version = ?
// after: guard existence of the column first
var colCount int
_ = db.QueryRow("SELECT COUNT(*) FROM information_schema.columns WHERE table_name='schema_migrations' AND column_name='content_hash'").Scan(&colCount)
if colCount == 0 {
    return fmt.Errorf("schema_migrations.content_hash column missing; run bd migrate repair")
}
Defensive patterns

Strategy: try-catch

Validate before calling

var hasCol int
_ = db.QueryRow("SELECT COUNT(*) FROM information_schema.columns WHERE table_name='schema_migrations' AND column_name='content_hash'").Scan(&hasCol)
if hasCol == 0 { /* backfill impossible; repair schema first */ }

Try / catch

if err := TryAutoResolveMergeConflicts(ctx, db); err != nil {
    if strings.Contains(err.Error(), "backfill content_hash") {
        // check locks / column existence, then retry settle once
        return retrySettle(ctx, db)
    }
    return err
}

Prevention

When it happens

Trigger: The UPDATE ... SET content_hash = ? WHERE version = ? statement fails — e.g. the content_hash column doesn't exist (older schema_migrations layout), the table is locked by another transaction, or the Dolt engine rejects the write mid-merge.

Common situations: Schema drift between clones where one lacks content_hash; a second bd process holding a write lock during merge settlement; embedded-engine transaction conflict on the migrations table.

Related errors


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