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
- Inspect the failure first: results = Searchkick.multi_search([q1, q2]); pp results.first.error - then fix the query it reports
- For unmapped vectors, declare knn: {embedding: {dimensions: ..., distance: ...}} in the model's searchkick options and reindex
- 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
- After every Searchkick.multi_search, branch on result.error before reading results
- Reindex after changing mappings/knn options so queries match the index schema
- Log the full error payload - it contains the exact Elasticsearch reason needed to fix the query
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
- Multiple clients found - set Searchkick.client_type = :elast
- No client found - install the `elasticsearch` or `opensearch
- Could not find class: #{class_name}
- #{class_name} is not a searchkick model
- Unknown quantization: #{quantization}
AI-assisted analysis of ankane/searchkick@93e901a75b (2026-08-21).
Data as JSON: /api/errors/3e4e04fc2a9dc153.
Report an issue: GitHub.