{"record":{"id":"4275e3bd9b07b551","repo":"ankane/pghero","slug":"invalid-query-hash-query-hash","errorCode":null,"errorMessage":"Invalid query hash: #{query_hash}","messagePattern":"Invalid query hash: #(.+?)","errorType":"validation","errorClass":"PgHero::Error","httpStatus":null,"severity":"error","filePath":"lib/pghero/methods/query_stats.rb","lineNumber":109,"sourceCode":"      end\n\n      def reset_query_stats(user: nil, query_hash: nil, raise_errors: false)\n        database = database_name\n        database_id = select_one(\"SELECT oid FROM pg_database WHERE datname = :database\", {database: database})\n        raise Error, \"Database not found: #{database}\" unless database_id\n\n        if user\n          user_id = select_one(\"SELECT usesysid FROM pg_user WHERE usename = :user\", {user: user})\n          raise Error, \"User not found: #{user}\" unless user_id\n        else\n          user_id = 0\n        end\n\n        if query_hash\n          query_id = query_hash.to_i\n          # may not be needed\n          # but not intuitive that all query hashes are reset with 0\n          raise Error, \"Invalid query hash: #{query_hash}\" if query_id == 0\n        else\n          query_id = 0\n        end\n\n        binds = {user_id: user_id, database_id: database_id, query_id: query_id}\n        # use execute to prevent \"unknown OID 2278\" warning\n        execute(\"SELECT pg_stat_statements_reset(:user_id, :database_id, :query_id)\", binds)\n        true\n      rescue ActiveRecord::StatementInvalid => e\n        raise e if raise_errors\n        false\n      end\n\n      # https://stackoverflow.com/questions/20582500/how-to-check-if-a-table-exists-in-a-given-schema\n      def historical_query_stats_enabled?\n        # TODO use schema from config\n        # make sure primary database is PostgreSQL first\n        queries_table_exists? && query_stats_table_exists? && capture_query_stats?","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/ankane/pghero/blob/7edb57986ffd36f9d64f0830c4ccc90a5eac46d6/lib/pghero/methods/query_stats.rb#L91-L127","documentation":"reset_query_stats(query_hash:) converts the argument with to_i and passes it as the queryid to pg_stat_statements_reset. In Postgres, 0 means \"all queries\", so PgHero refuses a converted value of 0 - which is what you get from nil, a non-numeric string, or a literal 0 - and raises Error \"Invalid query hash: {value}\" rather than silently resetting every statement's stats.","triggerScenarios":"database.reset_query_stats(query_hash: \"abc\") (to_i -> 0); query_hash: nil or \"0\"; passing a hash digest string from an older pghero/PG format instead of the numeric pg_stat_statements queryid; forwarding params[:query_hash] from a URL without validation.","commonSituations":"PG13+ / pg_stat_statements switched from md5 hash labels to bigint queryid, so old stored hashes no longer fit; hand-built admin URLs; API callers sending the wrong field.","solutions":["Pass the numeric queryid from the current query stats row (the query_hash value PgHero itself reports), as an Integer or numeric string","Validate before calling: query_hash = Integer(value, 10) rescue nil and skip when nil or 0","If you intend to reset everything, omit query_hash entirely instead of passing 0"],"exampleFix":"# before\ndatabase.reset_query_stats(query_hash: params[:query_hash])\n\n# after\nquery_hash = Integer(params[:query_hash], 10) rescue nil\ndatabase.reset_query_stats(query_hash: query_hash) if query_hash && query_hash > 0","handlingStrategy":"type-guard","validationCode":"query_hash = Integer(params[:query_hash], 10) rescue nil\ndatabase.reset_query_stats(query_hash: query_hash) if query_hash && query_hash > 0","typeGuard":"def valid_query_hash?(value)\n  n = Integer(value, 10) rescue nil\n  !n.nil? && n > 0\nend","tryCatchPattern":null,"preventionTips":["Validate with Integer(value, 10) at the request boundary; to_i silently maps garbage to 0","Use the numeric queryid pghero reports, not md5-style hashes from older pg_stat_statements versions"],"tags":["pghero","query-stats","validation","postgres"],"backgroundTag":"invalid-identifier","analyzedSha":"7edb57986ffd36f9d64f0830c4ccc90a5eac46d6","analyzedAt":"2026-08-21T17:33:54.942Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}