ankane/searchkick · error · Searchkick::Error

knn requires Elasticsearch 8.6+

Error message

knn requires Elasticsearch 8.6+

What it means

In Searchkick.multi_search, per-query failures come back as error payloads inside the msearch response rather than exceptions; Results#hits (and everything built on it - results, with_hit, suggestions) then raises Error 'Query error - use the error method to view it'. Calling .error on the results object returns the underlying Elasticsearch/OpenSearch error (unknown field, bad mapping, knn on an unmapped vector field, etc.).

Source

Thrown at lib/searchkick/index_options.rb:177

        settings[:number_of_shards] = 1
        settings[:number_of_replicas] = 0
      end

      if options[:similarity]
        settings[:similarity] = {default: {type: options[:similarity]}}
      end

      settings[:index] = {
        max_ngram_diff: 49,
        max_shingle_diff: 4
      }

      if options[:knn]
        unless Searchkick.knn_support?
          if Searchkick.opensearch?
            raise Error, "knn requires OpenSearch 2.4+"
          else
            raise Error, "knn requires Elasticsearch 8.6+"
          end
        end

        if Searchkick.opensearch? && options[:knn].any? { |_, v| !v[:distance].nil? }
          # only enable if doing approximate search
          settings[:index][:knn] = true
        end
      end

      add_synonyms(settings)
      add_search_synonyms(settings)

      if options[:special_characters] == false
        settings[:analysis][:analyzer].each_value do |analyzer_settings|
          analyzer_settings[:filter].reject! { |f| f == "asciifolding" }
        end
      end

View on GitHub (pinned to 93e901a75b)

Solutions

  1. Inspect the failure first: results = Searchkick.multi_search([q1, q2]); pp results.first.error - then fix the query it reports
  2. For unmapped vectors, declare knn: {embedding: {dimensions: ..., distance: ...}} in the model's searchkick options and reindex
  3. In multi_search flows, branch on result.error before touching .results so one bad query does not crash the page

Example fix

# before
q1, q2 = build_queries
results = Searchkick.multi_search([q1, q2])
results.first.results # => Searchkick::Error: Query error - use the error method to view it

# after
results = Searchkick.multi_search([q1, q2])
if (err = results.first.error)
  Rails.logger.error("search failed: #{err}")
  results.first.results # avoid; handle or return fallback
else
  results.first.results
end
Defensive patterns

Strategy: validation

Validate before calling

def safe_results(result)
  raise Searchkick::Error, result.error if result.error
  result.results
end

q1, q2 = build_queries
Searchkick.multi_search([q1, q2]).each { |r| safe_results(r) }

Type guard

def query_failed?(results)
  !results.error.nil?
end

Try / catch

begin
  results.first.hits
rescue Searchkick::Error
  err = results.first.error
  Rails.logger.error("search query failed: #{err}")
  [] # graceful fallback for this leg of the multi_search
end

Prevention

When it happens

Trigger: Searchkick.multi_search([keyword_query, knn_query]) where one query is invalid - e.g. knn against a field never mapped as a vector, or aggs on a text field without fielddata - then calling .results/.hits on that query's result object.

Common situations: Hybrid keyword+vector search where the vector field was never declared in searchkick knn: options or not reindexed; adding a new agg/filter without reindexing; one bad query poisoning a batched msearch while others succeed.

Related errors


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