gastownhall/beads · error

schema: read database name: %w

Error message

schema: read database name: %w

What it means

After pinning a connection, the schema initializer runs SELECT DATABASE() to learn which database the connection is scoped to; this error wraps a failure to scan that result. It means the pinned connection exists but the trivial query failed or returned no row (NULL database, e.g. no default schema selected).

Source

Thrown at internal/storage/dolt/store.go:2601

}

// initSchemaOnDBWithBootstrapHeal threads one-shot, incarnation-bound reset
// authority into the migration lock. A nil capability always fails closed.
func initSchemaOnDBWithBootstrapHeal(
	ctx context.Context,
	db *sql.DB,
	bootstrapHeal *schema.FreshBootstrapHealCapability,
	endpoint string,
) (int, error) {
	conn, err := db.Conn(ctx)
	if err != nil {
		return 0, fmt.Errorf("schema: pin connection: %w", err)
	}
	defer conn.Close()

	var dbName string
	if err := conn.QueryRowContext(ctx, "SELECT DATABASE()").Scan(&dbName); err != nil {
		return 0, fmt.Errorf("schema: read database name: %w", err)
	}

	var opts []schema.MigrateLockOption
	if bootstrapHeal != nil {
		opts = append(opts, schema.WithFreshBootstrapHeal(bootstrapHeal, endpoint))
	}
	applied, err := schema.MigrateUpWithLock(ctx, conn, dbName, opts...)
	if err != nil {
		return applied, fmt.Errorf("schema migration: %w", err)
	}
	return applied, nil
}

func initSchemaOnDBWithRetry(ctx context.Context, db *sql.DB) (int, error) {
	return initSchemaOnDBWithRetryAndGate(ctx, db, nil)
}

// initSchemaOnDBWithRetryAndGate is initSchemaOnDBWithRetry with an optional

View on GitHub (pinned to 71377f2769)

Solutions

  1. Include the database name in the DSN so DATABASE() is non-NULL
  2. Inspect the wrapped error: nil-row Scan (sql.ErrNoRows) means no default DB selected; driver errors mean check server health
  3. Retry after reconnecting; a stale pinned connection is re-pinned on the next call
  4. Verify ctx deadline is generous enough for pool pin + query

Example fix

// before
dsn := "user:pass@tcp(localhost:3306)/"
// after
dsn := "user:pass@tcp(localhost:3306)/mydb"
Defensive patterns

Strategy: validation

Validate before calling

// ensure DSN names a database so SELECT DATABASE() is non-NULL
cfg, err := mysql.ParseDSN(connStr)
if err != nil || cfg.DBName == "" {
    return fmt.Errorf("DSN must include a database name")
}

Try / catch

// Go: distinguish no-default-DB from driver failure
if err != nil {
    if errors.Is(err, sql.ErrNoRows) {
        // DATABASE() NULL: DSN missing dbname
    }
    return fmt.Errorf("schema: read database name: %w", err)
}

Prevention

When it happens

Trigger: initSchemaOnDBWithRetryAndGate executing conn.QueryRowContext(ctx, "SELECT DATABASE()").Scan(&dbName) when: the query errors (connection dropped, server gone, ctx canceled), or Scan fails because DATABASE() is NULL (connection without a database selected in the DSN).

Common situations: DSN missing the database name (e.g. 'user:pass@tcp(host:port)/' with empty dbname), Dolt server restarted between pin and query, context deadline exceeded, credentials revoked mid-session.

Related errors


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