ankane/pghero · error · ArgumentError

Invalid sort

Error message

Invalid sort

What it means

query_stats(sort:) orders current and historical stats by the given column; before touching the database it validates that sort is exactly "total_time", "average_time", or "calls" (strings). Any other value raises ArgumentError "Invalid sort". The sort value is also interpolated into SQL (it selects the average_time expression only when sort == "average_time"), hence the strict whitelist.

Source

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

  module Methods
    module QueryStats
      def query_stats(
        current: true,
        historical: false,
        limit: nil,
        sort: nil,
        user: nil,
        query_hash: nil,
        start_at: nil,
        end_at: nil,
        min_average_time: nil,
        min_calls: nil
      )
        limit ||= 100

        sort ||= "total_time"
        unless ["total_time", "average_time", "calls"].include?(sort)
          raise ArgumentError, "Invalid sort"
        end

        current_query_stats, current_total_time =
          if !current || (historical && end_at && end_at < Time.now)
            [[], 0]
          else
            current_query_stats(limit: limit, sort: sort, user: user, query_hash: query_hash)
          end

        historical_query_stats, historical_total_time =
          if historical && historical_query_stats_enabled?
            historical_query_stats(limit: limit, sort: sort, user: user, query_hash: query_hash, start_at: start_at, end_at: end_at)
          else
            [[], 0]
          end

        query_stats = current_query_stats + historical_query_stats
        query_stats = combine_query_stats(query_stats.group_by { |q| [q[:query_hash], q[:user]] })

View on GitHub (pinned to 7edb57986f)

Solutions

  1. Pass one of the exact strings: "total_time", "average_time", or "calls" (sort is optional and defaults to "total_time")
  2. Whitelist request input: sort = %w[total_time average_time calls].include?(params[:sort]) ? params[:sort] : nil
  3. Convert symbols at the boundary with to_s if your code stores symbols

Example fix

# before
database.query_stats(sort: params[:sort])

# after
sort = %w[total_time average_time calls].include?(params[:sort]) ? params[:sort] : nil
database.query_stats(sort: sort)
Defensive patterns

Strategy: validation

Validate before calling

sort = params[:sort] if %w[total_time average_time calls].include?(params[:sort])
database.query_stats(sort: sort)

Type guard

def valid_query_stats_sort?(value)
  %w[total_time average_time calls].include?(value)
end

Prevention

When it happens

Trigger: database.query_stats(sort: "total") (abbreviated); sort: :calls as a symbol; forwarding params[:sort] from a custom controller or API without whitelisting; copying code that used an older allowed value.

Common situations: Custom dashboards built on PgHero's query_stats; API endpoints exposing the sort parameter to users; scheduled reports hardcoding a column label.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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