ankane/searchkick · error · Searchkick::Error
#{class_name} is not a searchkick model
Error message
#{class_name} is not a searchkick model What it means
For exact kNN on Elasticsearch, Searchkick maps the distance metric to a Painless script function (cosineSimilarity, l2norm, l1norm, dotProduct). Only 'cosine', 'euclidean', 'taxicab' and 'inner_product' are supported on this branch; any other value - including 'chebyshev', which only the OpenSearch branch supports - raises ArgumentError 'Unknown distance: ...'.
Source
Thrown at lib/searchkick.rb:307
raise Error, "Need primary key to load records" if !primary_key
relation.where(primary_key => ids)
elsif relation.respond_to?(:queryable)
relation.queryable.for_ids(ids)
end
raise Error, "Not sure how to load records" if !relation
relation
end
# public (for reindexing conversions)
def self.load_model(class_name, allow_child: false)
model = class_name.safe_constantize
raise Error, "Could not find class: #{class_name}" unless model
if allow_child
unless model.respond_to?(:searchkick_klass)
raise Error, "#{class_name} is not a searchkick model"
end
else
unless Searchkick.models.include?(model)
raise Error, "#{class_name} is not a searchkick model"
end
end
model
end
# private
def self.indexer
Thread.current[:searchkick_indexer] ||= Indexer.new
end
# private
def self.callbacks_value
Thread.current[:searchkick_callbacks_enabled]
endView on GitHub (pinned to 93e901a75b)
Solutions
- Use 'cosine', 'euclidean', 'taxicab' or 'inner_product'
- For chebyshev on Elasticsearch, compute it via where: {_script: Searchkick::Script.new(...)} or switch the exact query to OpenSearch
- Verify exact lowercase spelling of the metric string
Example fix
# before
Product.search('*', knn: {field: :v, vector: vec, distance: 'chebyshev', exact: true})
# => ArgumentError: Unknown distance: chebyshev (Elasticsearch branch)
# after
Product.search('*', knn: {field: :v, vector: vec, distance: 'cosine', exact: true}) Defensive patterns
Strategy: type-guard
Type guard
ES_EXACT_DISTANCES = %w[cosine euclidean taxicab inner_product].freeze
def valid_es_exact_distance?(value)
ES_EXACT_DISTANCES.include?(value)
end
raise ArgumentError, "bad distance: #{d}" unless valid_es_exact_distance?(d)
Product.search('*', knn: {field: :v, vector: vec, distance: d, exact: true}) Try / catch
begin
Product.search('*', knn: opts)
rescue ArgumentError => e
raise unless e.message.start_with?('Unknown distance')
opts[:distance] = 'cosine'
Product.search('*', knn: opts)
end Prevention
- Validate metric names against a per-server constant (Elasticsearch has no chebyshev)
- Map external metric vocabularies to Searchkick names in one adapter
- Test knn queries on both server flavors if you deploy both
When it happens
Trigger: Product.search('*', knn: {field: :embedding, vector: vec, distance: 'chebyshev', exact: true}) on Elasticsearch; values like 'dot_product', 'l2' or 'Cosine'.
Common situations: Sharing query code between OpenSearch and Elasticsearch deployments; porting metric names from Faiss or sentence-transformers examples; typos and casing mistakes.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Use Searchkick.search to search multiple models
- Need primary key to load records
- Could not find class: #{class_name}
- Multiple clients found - set Searchkick.client_type = :elast
- No client found - install the `elasticsearch` or `opensearch
AI-assisted analysis of ankane/searchkick@93e901a75b (2026-08-21).
Data as JSON: /api/errors/3cceae77748d3f05.
Report an issue: GitHub.