{"record":{"id":"2e8a451d0a46b11b","repo":"ankane/searchkick","slug":"no-client-found-install-the-elasticsearch-or","errorCode":null,"errorMessage":"No client found - install the `elasticsearch` or `opensearch-ruby` gem","messagePattern":"No client found - install the `elasticsearch` or `opensearch-ruby` gem","errorType":"exception","errorClass":"Searchkick::Error","httpStatus":null,"severity":"error","filePath":"lib/searchkick.rb","lineNumber":85,"sourceCode":"  self.models = []\n  self.client_options = {}\n  self.queue_name = :searchkick\n  self.model_options = {}\n  self.parent_job = \"ActiveJob::Base\"\n\n  def self.client\n    @client ||= begin\n      client_type =\n        if self.client_type\n          self.client_type\n        elsif defined?(OpenSearch::Client) && defined?(Elasticsearch::Client)\n          raise Error, \"Multiple clients found - set Searchkick.client_type = :elasticsearch or :opensearch\"\n        elsif defined?(OpenSearch::Client)\n          :opensearch\n        elsif defined?(Elasticsearch::Client)\n          :elasticsearch\n        else\n          raise Error, \"No client found - install the `elasticsearch` or `opensearch-ruby` gem\"\n        end\n\n      if client_type == :opensearch\n        OpenSearch::Client.new({\n          url: ENV[\"OPENSEARCH_URL\"],\n          transport_options: {request: {timeout: timeout}},\n          retry_on_failure: 2\n        }.deep_merge(client_options)) do |f|\n          f.use Searchkick::Middleware\n          f.request :aws_sigv4, signer_middleware_aws_params if aws_credentials\n        end\n      else\n        raise Error, \"The `elasticsearch` gem must be 8+\" if Elasticsearch::VERSION.to_i < 8\n\n        Elasticsearch::Client.new({\n          url: ENV[\"ELASTICSEARCH_URL\"],\n          transport_options: {request: {timeout: timeout}},\n          retry_on_failure: 2","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/ankane/searchkick/blob/93e901a75b11a25101668a616e006b158251b16e/lib/searchkick.rb#L67-L103","documentation":"Searchkick's suggest option adds an Elasticsearch phrase suggester for each suggest-enabled field. Suggest fields come either from an explicit array (suggest: [:name, :brand]) or from the model's searchkick suggest: [...] settings, intersected with any fields: option. If that set ends up empty there is nothing to build a suggester for, and Searchkick raises ArgumentError 'Must pass fields to suggest option' while preparing the payload.","triggerScenarios":"Product.search('milkm', suggest: true) on a model that does not declare searchkick suggest: [:name]; passing suggest: true together with fields: [:brand] when the only suggest field is :name (intersection is empty); passing suggest: [] explicitly.","commonSituations":"Enabling did-you-mean suggestions on a search box before adding suggest: [...] to the model's searchkick call and reindexing; restricting a search with fields: that excludes all suggest fields; renaming indexed fields without updating the suggest setting.","solutions":["Declare suggest fields on the model - searchkick suggest: [:name] - and reindex so the .suggest subfield mapping exists","Or pass fields at query time: Product.search('milkm', suggest: [:name])","If you also pass fields:, make sure it overlaps the model's suggest fields (the intersection must be non-empty)"],"exampleFix":"# before\nclass Product < ApplicationRecord\n  searchkick # no suggest fields\nend\nProduct.search('milkm', suggest: true) # => ArgumentError\n\n# after\nclass Product < ApplicationRecord\n  searchkick suggest: [:name]\nend\nProduct.reindex\nProduct.search('milkm', suggest: true)","handlingStrategy":"validation","validationCode":"def searchable_suggest_fields(model)\n  fields = model.searchkick_options[:suggest] || []\n  fields = fields & params_fields if params_fields\n  fields\nend\n\nraise ArgumentError, 'no suggest fields' if searchable_suggest_fields(Product).empty?\nProduct.search(term, suggest: true)","typeGuard":null,"tryCatchPattern":"begin\n  Product.search(term, suggest: true).suggestions\nrescue ArgumentError\n  [] # model has no suggest fields configured\nend","preventionTips":["Declare suggest: [...] on the model at the same time you add suggest: true to queries, then reindex","When passing fields: alongside suggest, assert the overlap is non-empty in a helper","Add an integration test that calls .suggestions after reindexing"],"tags":["searchkick","suggestions","phrase-suggester","argumenterror","elasticsearch"],"backgroundTag":"missing-required-argument","analyzedSha":"93e901a75b11a25101668a616e006b158251b16e","analyzedAt":"2026-08-21T19:06:23.767Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}