ankane/pghero · warning · PgHero::NotEnabled

Suggested indexes not enabled

Error message

Suggested indexes not enabled

What it means

PgHero raises this from PgHero::Methods::SuggestedIndexes#suggested_indexes_by_query when suggested_indexes_enabled? is false. That predicate requires three things: the PgQuery gem is loaded, its version is >= 6, and query_stats_enabled? is true (pg_stat_statements is installed and readable). Suggested indexes work by parsing the SQL text of your most time-consuming queries (historical query stats from the last 24 hours), so without a modern pg_query parser and query stats there is nothing to analyze.

Source

Thrown at lib/pghero/methods/suggested_indexes.rb:58

                  indexes += existing_columns["gist"][index[:table]]

                  # hash indexes work for equality
                  indexes += existing_columns["hash"][index[:table]] if best_index[:structure][:where].all? { |v| v[:op] == "=" }

                  # brin indexes work for all
                  indexes += existing_columns["brin"][index[:table]]
                end

                covering_index = indexes.find { |e| index_covers?(e.map { |v| v.delete_suffix(" inet_ops") }, index[:columns]) }
                if covering_index
                  best_index[:covering_index] = covering_index
                  best_index[:explanation] = "Covered by index on (#{covering_index.join(", ")})"
                end
              end
            end
          end
        else
          raise NotEnabled, "Suggested indexes not enabled"
        end

        best_indexes
      end

      def suggested_indexes(suggested_indexes_by_query: nil, **options)
        indexes = []

        (suggested_indexes_by_query || self.suggested_indexes_by_query(**options)).select { |_s, i| i[:found] && !i[:covering_index] }.group_by { |_s, i| i[:index] }.each do |index, group|
          details = {}
          group.map(&:second).each do |g|
            details = details.except(:index).deep_merge(g)
          end
          indexes << index.merge(queries: group.map(&:first), details: details)
        end

        indexes.sort_by { |i| [i[:table], i[:columns]] }
      end

View on GitHub (pinned to 7edb57986f)

Solutions

  1. Add `gem "pg_query", ">= 6"` to your Gemfile and run `bundle install` (verify with PgHero.suggested_indexes_enabled?).
  2. Make pg_stat_statements available: ensure shared_preload_libraries includes it in postgresql.conf (restart required), then PgHero.enable_query_stats or `CREATE EXTENSION pg_stat_statements`.
  3. Confirm queries exist to analyze: query_stats_enabled? must be true and there must be captured stats (for historical input, the pghero_query_stats capture job must have run).
  4. If intentionally disabled, guard with `PgHero.suggested_indexes_enabled?` or rescue PgHero::NotEnabled.

Example fix

# before - raises PgHero::NotEnabled: Suggested indexes not enabled
PgHero.suggested_indexes

# after
# Gemfile:
#   gem "pg_query", ">= 6"
# postgresql.conf:
#   shared_preload_libraries = 'pg_stat_statements'
# then: CREATE EXTENSION pg_stat_statements; (or PgHero.enable_query_stats)
indexes = PgHero.suggested_indexes if PgHero.suggested_indexes_enabled?
Defensive patterns

Strategy: validation

Validate before calling

return unless PgHero.suggested_indexes_enabled?
suggestions = PgHero.suggested_indexes

Type guard

def suggested_indexes_available?
  PgHero.suggested_indexes_enabled? # pg_query >= 6 present AND query stats readable
end

Try / catch

begin
  PgHero.suggested_indexes
rescue PgHero::NotEnabled
  Rails.logger.info("Suggested indexes unavailable (needs pg_query >= 6 and pg_stat_statements)")
  []
end

Prevention

When it happens

Trigger: Calling PgHero.suggested_indexes or PgHero.suggested_indexes_by_query when the pg_query gem is absent from the bundle (it is an optional dependency) or pinned below version 6; or when pg_stat_statements is not installed/preloaded so query_stats_enabled? returns false; the web UI suggested-indexes tab hits the same path.

Common situations: Upgrading pghero to a version requiring pg_query 6 while Gemfile.lock still holds pg_query 4/5; deploying to production where pg_stat_statements was never in shared_preload_libraries; using a managed Postgres plan that disallows the extension; JRuby or platforms where the pg_query native extension failed to build.

Related errors


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