ankane/searchkick · error · Searchkick::Error
Requires non-OSS version of Elasticsearch
Error message
Requires non-OSS version of Elasticsearch
What it means
The exists where-operator accepts only true or false, mapping to an exists filter or a must_not-exists filter respectively. Any other value raises ArgumentError because Elasticsearch has no meaningful query for exists: nil, exists: 'true' or exists: 1.
Source
Thrown at lib/searchkick/index.rb:198
RecordData.new(self, record).document_type
end
def similar_record(record, **options)
options[:per_page] ||= 10
options[:similar] = [RecordData.new(self, record).record_data]
options[:models] ||= [record.class] unless options.key?(:model)
Searchkick.search("*", **options)
end
def reload_synonyms
if Searchkick.opensearch?
client.transport.perform_request "POST", "_plugins/_refresh_search_analyzers/#{CGI.escape(name)}"
else
begin
client.transport.perform_request("GET", "#{CGI.escape(name)}/_reload_search_analyzers")
rescue => e
raise Error, "Requires non-OSS version of Elasticsearch" if Searchkick.not_allowed_error?(e)
raise e
end
end
end
# queue
def reindex_queue
ReindexQueue.new(name)
end
# reindex
# note: this is designed to be used internally
# so it does not check object matches index class
def reindex(object, method_name: nil, ignore_missing: nil, full: false, **options)
if @options[:job_options]
options[:job_options] = (@options[:job_options] || {}).merge(options[:job_options] || {})View on GitHub (pinned to 93e901a75b)
Solutions
- Pass real booleans: where: {description: {exists: true}}
- Coerce params first: ActiveModel::Type::Boolean.new.cast(params[:has_desc]) or params == 'true'
- To match missing values use exists: false rather than exists: nil
Example fix
# before
Product.search('*', where: {description: {exists: params[:has_desc]}}) # params value can be nil/'true'
# => ArgumentError: Passing a value other than true or false to exists is not supported
# after
Product.search('*', where: {description: {exists: ActiveModel::Type::Boolean.new.cast(params[:has_desc])}}) Defensive patterns
Strategy: type-guard
Type guard
BOOL = ->(v) { v.nil? ? nil : ActiveModel::Type::Boolean.new.cast(v) }
def exists_filter(v)
bool = BOOL.call(v)
raise ArgumentError, 'exists must be true/false' unless bool == true || bool == false
{exists: bool}
end
Product.search('*', where: {description: exists_filter(params[:has_desc])}) Prevention
- Coerce all incoming filter params through ActiveModel::Type::Boolean before building where hashes
- Reject or default nil rather than passing it through
- Keep a sanitizer between request params and the where option
When it happens
Trigger: Product.search('*', where: {description: {exists: nil}}); where: {email: {exists: 'true'}} or {exists: 1} when filters are built from unconverted request params.
Common situations: Building filters from query strings where booleans arrive as 'true'/'false' strings or nil; JSON payloads using 0/1 flags; assuming nil works like false (use exists: false for missing fields).
Related errors
- Cannot reindex object
- Multiple clients found - set Searchkick.client_type = :elast
- No client found - install the `elasticsearch` or `opensearch
- The `elasticsearch` gem must be 8+
- Use Searchkick.search to search multiple models
AI-assisted analysis of ankane/searchkick@93e901a75b (2026-08-21).
Data as JSON: /api/errors/3aca82c80c7a267e.
Report an issue: GitHub.