ankane/searchkick · error · ArgumentError

Must specify fields to search

Error message

Must specify fields to search

What it means

For `similar:` (more_like_this) queries, Elasticsearch requires concrete field names — a wildcard like `*.analyzed` cannot back an mlt query. `set_fields` returns wildcards when no explicit fields/searchable/default_fields are configured, so the similar-branch raises `ArgumentError` when every resolved field starts with `*.`.

Source

Thrown at lib/searchkick/query.rb:288

          :profile, :select, :smart_aggs, :suggest, :where]
        raise ArgumentError, "Options incompatible with body option: #{ignored_options.join(", ")}" if ignored_options.any?
        payload = @json
      else
        must_not = []
        should = []

        if options[:similar]
          like = options[:similar] == true ? term : options[:similar]
          query = {
            more_like_this: {
              like: like,
              min_doc_freq: 1,
              min_term_freq: 1,
              analyzer: "searchkick_search2"
            }
          }
          if fields.all? { |f| f.start_with?("*.") }
            raise ArgumentError, "Must specify fields to search"
          end
          if fields != ["_all"]
            query[:more_like_this][:fields] = fields
          end
        elsif all && !options[:exclude]
          query = {
            match_all: {}
          }
        else
          queries = []

          misspellings =
            if options.key?(:misspellings)
              options[:misspellings]
            else
              true
            end

View on GitHub (pinned to 93e901a75b)

Solutions

  1. Specify concrete fields at query time: `Product.search(product.name, fields: [:name, :description], similar: true)`.
  2. Or set them on the model: `searchkick searchable: [:name, :description]`, then reindex.
  3. If the model relies on `_all`, re-enable it (`_all: true`) so the similar query can target `_all` instead of wildcards.
  4. Remember `similar: true` uses the search term as the like-text; pass the source text via `similar: record.name` for record-based similarity.

Example fix

# before
Product.search("organic whole milk", similar: true)
# => ArgumentError: Must specify fields to search

# after
Product.search("organic whole milk", fields: [:name, :description], similar: true)
Defensive patterns

Strategy: validation

Validate before calling

def similar_products(record, fields: %i[name description])
  raise ArgumentError, "similar requires explicit fields" if fields.blank? || fields.all? { |f| f.to_s.start_with?("*") }
  record.class.search(record.name, fields: fields, similar: true, load: false)
end

Type guard

def similar_fields_valid?(fields)
  fields.present? && !fields.map(&:to_s).all? { |f| f.start_with?("*.") }
end

Prevention

When it happens

Trigger: `Product.search("text", similar: true)` (or `similar: "some text"`) on a model that sets no `searchable:`/`fields:` and has `_all` disabled; or explicitly passing `fields: ["*_analyzed"]`-style wildcards with `similar:`. The check runs at query build, before any request.

Common situations: Adding a 'related items' feature with `similar: true` to a model indexed with `searchable: false`-style defaults or `_all: false`; copying the README's similar example without the `fields:` line; migrating from old `_all`-based configs where similar used to work implicitly.

Related errors


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