ankane/pghero · error · PgHero::Error

Database not found: #{database}

Error message

Database not found: #{database}

What it means

reset_query_stats must pass the current database's oid to pg_stat_statements_reset(user_id, database_id, query_id). It looks the oid up with SELECT oid FROM pg_database WHERE datname = :database using database_name; if that catalog query returns nil, PgHero raises Error "Database not found: {name}". Since you are by definition connected to that database, a nil result points at the connection not reporting the name that actually appears in pg_database.

Source

Thrown at lib/pghero/methods/query_stats.rb:96

        true
      rescue ActiveRecord::StatementInvalid
        false
      end

      def enable_query_stats
        execute("CREATE EXTENSION IF NOT EXISTS pg_stat_statements")
        true
      end

      def disable_query_stats
        execute("DROP EXTENSION IF EXISTS pg_stat_statements")
        true
      end

      def reset_query_stats(user: nil, query_hash: nil, raise_errors: false)
        database = database_name
        database_id = select_one("SELECT oid FROM pg_database WHERE datname = :database", {database: database})
        raise Error, "Database not found: #{database}" unless database_id

        if user
          user_id = select_one("SELECT usesysid FROM pg_user WHERE usename = :user", {user: user})
          raise Error, "User not found: #{user}" unless user_id
        else
          user_id = 0
        end

        if query_hash
          query_id = query_hash.to_i
          # may not be needed
          # but not intuitive that all query hashes are reset with 0
          raise Error, "Invalid query hash: #{query_hash}" if query_id == 0
        else
          query_id = 0
        end

        binds = {user_id: user_id, database_id: database_id, query_id: query_id}

View on GitHub (pinned to 7edb57986f)

Solutions

  1. Check what the server reports: run database.select_value("SELECT current_database()") and compare with SELECT datname FROM pg_database
  2. Connect directly to the target Postgres (bypass the pooler/proxy) for stats-reset operations
  3. Reconnect after database renames so cached metadata is refreshed
Defensive patterns

Strategy: try-catch

Validate before calling

db_name = database.select_value("SELECT current_database()")
database.reset_query_stats if database.select_one("SELECT oid FROM pg_database WHERE datname = :d", {d: db_name})

Try / catch

begin
  database.reset_query_stats
rescue PgHero::Error => e
  # catalog mismatch is environmental (pooler/proxy); log and continue rather than retrying
  Rails.logger.warn("reset_query_stats skipped: #{e.message}")
end

Prevention

When it happens

Trigger: Connecting through a pooler/proxy (pgbouncer, RDS Proxy) that authenticates against one database and routes to another, so current_database() differs from the catalog entry; unusual role permissions that hide the row in pg_database; a database_name that was renamed while a pooled connection stayed alive.

Common situations: Containerized deployments behind pgbouncer in transaction mode; managed Postgres with a proxy layer; retrying reset_query_stats after a database rename on a stale connection.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of ankane/pghero@7edb57986f (2026-08-21). Data as JSON: /api/errors/d2c4eb529d390378. Report an issue: GitHub.