gastownhall/beads · warning

unknown column content_hash in schema_migrations at %q

Error message

unknown column content_hash in schema_migrations at %q

What it means

After confirming schema_migrations exists at the ref, the code probes "SHOW COLUMNS ... LIKE 'content_hash'"; if the column is absent at that commit, this error is returned. It means the ref predates the content_hash column addition — schema existed but the newer column hadn't been migrated in yet.

Source

Thrown at internal/storage/schema/migration_content_hashes.go:72

		// it: letting the SELECT fail emits a Dolt server warning for every
		// read-only doctor run.
		//nolint:gosec // G201: ref is validated above — AS OF requires a literal, not a bind param
		hasTable, queryErr := queryHasRows(ctx, db,
			fmt.Sprintf("SHOW TABLES AS OF '%s' LIKE 'schema_migrations'", ref))
		if queryErr != nil {
			return nil, queryErr
		}
		if !hasTable {
			return nil, fmt.Errorf("table not found: schema_migrations at %q", ref)
		}
		//nolint:gosec // G201: ref is validated above — AS OF requires a literal, not a bind param
		hasContentHash, queryErr := queryHasRows(ctx, db,
			fmt.Sprintf("SHOW COLUMNS FROM schema_migrations AS OF '%s' LIKE 'content_hash'", ref))
		if queryErr != nil {
			return nil, queryErr
		}
		if !hasContentHash {
			return nil, fmt.Errorf("unknown column content_hash in schema_migrations at %q", ref)
		}
		//nolint:gosec // G201: ref is validated above — AS OF requires a literal, not a bind param
		rows, err = db.QueryContext(ctx,
			fmt.Sprintf("SELECT version, content_hash FROM schema_migrations AS OF '%s'", ref))
	}
	if err != nil {
		return nil, err
	}
	defer rows.Close()

	out := map[int]string{}
	for rows.Next() {
		var version int
		var hash sql.NullString
		if err := rows.Scan(&version, &hash); err != nil {
			return nil, err
		}
		if hash.Valid && hash.String != "" {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Update the ref to a commit at or after the content_hash migration (e.g. latest remote main).
  2. Run `bd dolt pull` / sync the remote so it contains the newer migration, then retry.
  3. If old history must be handled, catch this case and treat content hashes as absent for that ref.
  4. Apply pending migrations so both sides share the content_hash column.

Example fix

// before: fail on old remote
hashes, err := schema.ReadMigrationContentHashes(ctx, db, ref)
// after: treat column-less history as empty hashes
hashes, err := schema.ReadMigrationContentHashes(ctx, db, ref)
if err != nil && strings.Contains(err.Error(), "unknown column content_hash") {
    return map[string]string{}, nil
}
Defensive patterns

Strategy: fallback

Try / catch

hashes, err := schema.ReadMigrationContentHashes(ctx, db, ref)
if err != nil && strings.Contains(err.Error(), "unknown column content_hash") {
    hashes = map[string]string{} // ref predates content_hash column
}

Prevention

When it happens

Trigger: Calling ReadMigrationContentHashes with a ref where schema_migrations exists but lacks the content_hash column (intermediate schema history); comparing against a remote that hasn't pulled the content-hash migration.

Common situations: Mixed-version deployments where one replica/repo has newer migrations than the ref being compared; doctor run against an out-of-date remote branch; partially applied migration history.

Related errors


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