ankane/searchkick · error · ArgumentError
Unknown distance: #{distance}
Error message
Unknown distance: #{distance} What it means
When building the OpenSearch `knn_vector` mapping, searchkick translates your `distance` string into an OpenSearch `space_type` via a fixed case statement: `"cosine"`→`cosinesimil`, `"euclidean"`→`l2`, `"inner_product"`→`innerproduct`. Any other value has no translation, so it raises `ArgumentError` rather than sending an invalid space_type to the server.
Source
Thrown at lib/searchkick/index_options.rb:459
raise ArgumentError, "Must specify a distance for OpenSearch"
end
vector_options = {
type: "knn_vector",
dimension: knn_options[:dimensions]
}
if !distance.nil?
space_type =
case distance
when "cosine"
"cosinesimil"
when "euclidean"
"l2"
when "inner_product"
"innerproduct"
else
raise ArgumentError, "Unknown distance: #{distance}"
end
if !quantization.nil?
raise ArgumentError, "Quantization not supported yet for OpenSearch"
end
vector_options[:method] = {
name: "hnsw",
space_type: space_type,
engine: "lucene",
parameters: knn_options.slice(:m, :ef_construction)
}
end
mapping[field.to_s] = vector_options
else
vector_options = {
type: "dense_vector",View on GitHub (pinned to 93e901a75b)
Solutions
- Use one of the three accepted strings: `distance: "cosine"`, `distance: "euclidean"`, or `distance: "inner_product"`.
- Do not pass raw OpenSearch space_types or ES similarities — searchkick normalizes both platforms from the three abstract values.
- If you need an unsupported metric, drop to a hand-written `mappings:`/`merge_mappings` config for that field.
- Reindex after changing the knn config.
Example fix
# before
searchkick knn: {embedding: {dimensions: 768, distance: "cosinesimil"}}
# OpenSearch => ArgumentError: Unknown distance: cosinesimil
# after
searchkick knn: {embedding: {dimensions: 768, distance: "cosine"}} Defensive patterns
Strategy: validation
Validate before calling
SUPPORTED_DISTANCES = %w[cosine euclidean inner_product].freeze
knn = {embedding: {dimensions: 768, distance: "cosine"}}
bad = knn.select { |_, o| !SUPPORTED_DISTANCES.include?(o[:distance]) }
raise ArgumentError, "unsupported distances: #{bad.keys.join(', ')}" if bad.any?
class Product < ApplicationRecord
searchkick knn: knn
end Type guard
def valid_knn_distance?(distance) %w[cosine euclidean inner_product].include?(distance) end
Prevention
- Use searchkick's three abstract distance names; never paste raw space_types (cosinesimil) or ES similarities (l2_norm) into `distance`.
- Keep knn config in one constant so a typo fails once at boot, not per index build.
- Add a spec asserting the knn mapping builds (call the private index_options in a test) after config edits.
When it happens
Trigger: `searchkick knn: {embedding: {dimensions: 768, distance: "dot_product"}}` (or `"l2"`, `"cosinesimil"`, `"l2_norm"`, or any typo) on OpenSearch, followed by reindex/index creation.
Common situations: Copy-pasting OpenSearch's own space_type names (`cosinesimil`, `l2`, `innerproduct`) instead of searchkick's abstracted `distance` names; copy-pasting Elasticsearch similarity names (`l2_norm`, `max_inner_product`, `dot_product`) which the OpenSearch branch does not accept; using a vector-embedding vendor's default metric name verbatim.
Related errors
- Use Searchkick.search to search multiple models
- Redis not configured
- Need primary key to load records
- Must specify a distance for OpenSearch
- Quantization not supported yet for OpenSearch
AI-assisted analysis of ankane/searchkick@93e901a75b (2026-08-21).
Data as JSON: /api/errors/c8e157a2a8f64cbd.
Report an issue: GitHub.