ankane/searchkick · error · Searchkick::Error

No client found - install the `elasticsearch` or `opensearch

Error message

No client found - install the `elasticsearch` or `opensearch-ruby` gem

What it means

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.

Source

Thrown at lib/searchkick.rb:85

  self.models = []
  self.client_options = {}
  self.queue_name = :searchkick
  self.model_options = {}
  self.parent_job = "ActiveJob::Base"

  def self.client
    @client ||= begin
      client_type =
        if self.client_type
          self.client_type
        elsif defined?(OpenSearch::Client) && defined?(Elasticsearch::Client)
          raise Error, "Multiple clients found - set Searchkick.client_type = :elasticsearch or :opensearch"
        elsif defined?(OpenSearch::Client)
          :opensearch
        elsif defined?(Elasticsearch::Client)
          :elasticsearch
        else
          raise Error, "No client found - install the `elasticsearch` or `opensearch-ruby` gem"
        end

      if client_type == :opensearch
        OpenSearch::Client.new({
          url: ENV["OPENSEARCH_URL"],
          transport_options: {request: {timeout: timeout}},
          retry_on_failure: 2
        }.deep_merge(client_options)) do |f|
          f.use Searchkick::Middleware
          f.request :aws_sigv4, signer_middleware_aws_params if aws_credentials
        end
      else
        raise Error, "The `elasticsearch` gem must be 8+" if Elasticsearch::VERSION.to_i < 8

        Elasticsearch::Client.new({
          url: ENV["ELASTICSEARCH_URL"],
          transport_options: {request: {timeout: timeout}},
          retry_on_failure: 2

View on GitHub (pinned to 93e901a75b)

Solutions

  1. Declare suggest fields on the model - searchkick suggest: [:name] - and reindex so the .suggest subfield mapping exists
  2. Or pass fields at query time: Product.search('milkm', suggest: [:name])
  3. If you also pass fields:, make sure it overlaps the model's suggest fields (the intersection must be non-empty)

Example fix

# before
class Product < ApplicationRecord
  searchkick # no suggest fields
end
Product.search('milkm', suggest: true) # => ArgumentError

# after
class Product < ApplicationRecord
  searchkick suggest: [:name]
end
Product.reindex
Product.search('milkm', suggest: true)
Defensive patterns

Strategy: validation

Validate before calling

def searchable_suggest_fields(model)
  fields = model.searchkick_options[:suggest] || []
  fields = fields & params_fields if params_fields
  fields
end

raise ArgumentError, 'no suggest fields' if searchable_suggest_fields(Product).empty?
Product.search(term, suggest: true)

Try / catch

begin
  Product.search(term, suggest: true).suggestions
rescue ArgumentError
  [] # model has no suggest fields configured
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of ankane/searchkick@93e901a75b (2026-08-21). Data as JSON: /api/errors/2e8a451d0a46b11b. Report an issue: GitHub.