gastownhall/beads · warning

table not found: schema_migrations at %q

Error message

table not found: schema_migrations at %q

What it means

When reading at a historical ref, the code first probes "SHOW TABLES AS OF '<ref>' LIKE 'schema_migrations'"; if the table did not exist at that commit, this error is returned. It is informational about history: the cached ref predates the introduction of schema_migrations, so no migration hashes can be read at that point.

Source

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

	)
	if ref == "" {
		rows, err = db.QueryContext(ctx, "SELECT version, content_hash FROM schema_migrations")
	} else {
		if verr := validateMigrationRef(ref); verr != nil {
			return nil, fmt.Errorf("invalid ref: %w", verr)
		}
		// A cached ref may legitimately predate schema_migrations or its
		// content_hash column. Probe the historical shape before selecting from
		// 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()

View on GitHub (pinned to 71377f2769)

Solutions

  1. Point the ref at a commit where schema_migrations exists (e.g. current remote main after migrations ran).
  2. Run migrations on the remote/repo so schema_migrations exists at the ref.
  3. If the ref legitimately predates migrations, treat as "no migrations" in the caller instead of failing (check errors.Is/contains).
  4. Sync/pull the remote so the ref resolves to a recent commit.

Example fix

// before: hard failure on ancient ref
hashes, err := schema.ReadMigrationContentHashes(ctx, db, ref)
if err != nil { return err }
// after: tolerate pre-migrations history
hashes, err := schema.ReadMigrationContentHashes(ctx, db, ref)
if err != nil && strings.Contains(err.Error(), "table not found: schema_migrations") {
    hashes = map[string]string{} // no migrations at ref
    return hashes, nil
}
Defensive patterns

Strategy: fallback

Try / catch

hashes, err := schema.ReadMigrationContentHashes(ctx, db, ref)
if err != nil && strings.Contains(err.Error(), "table not found: schema_migrations") {
    hashes = map[string]string{} // ref predates migrations table
}

Prevention

When it happens

Trigger: Calling ReadMigrationContentHashes with a ref pointing to a commit before schema_migrations was created — e.g. an old remote head, a freshly cloned repo whose ref predates the migrations framework, or comparing against a wrong/very old ref.

Common situations: Remote branch not yet pulled/migrated; comparing current DB against an ancient commit; newly initialized database where migrations haven't run at the ref; typos resolving to an old tag.

Related errors


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