ankane/searchkick · error · Searchkick::Error

knn requires OpenSearch 2.4+

Error message

knn requires OpenSearch 2.4+

What it means

reindex(resume: true) skips already-indexed records by comparing against the index's total docs using relation.primary_key and an arel greater-than condition - Active Record only API. Mongoid relations do not respond to primary_key, so resume_relation raises Error 'Resume not supported for Mongoid'.

Source

Thrown at lib/searchkick/index_options.rb:175

      if Searchkick.env == "test"
        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

View on GitHub (pinned to 93e901a75b)

Solutions

  1. Run the full reindex without resume: Product.reindex
  2. For long-running Mongoid reindexes, use mode: :async or :queue with batches and restart from scratch on failure
  3. Narrow the work with a where(...) scope instead of resuming

Example fix

# before
Product.reindex(resume: true) # Mongoid model
# => Searchkick::Error: Resume not supported for Mongoid

# after
Product.reindex # full reindex, no resume
# or scope the work
Product.where(created_at: 2.days.ago..).reindex
Defensive patterns

Strategy: validation

Validate before calling

def reindex_with_resume?(relation)
  relation.respond_to?(:primary_key) # Active Record only
end

Product.reindex(resume: reindex_with_resume?(Product.all) && user_wants_resume)

Try / catch

begin
  Product.reindex(resume: true)
rescue Searchkick::Error => e
  raise unless e.message == 'Resume not supported for Mongoid'
  Product.reindex # full reindex fallback
end

Prevention

When it happens

Trigger: Calling Product.reindex(resume: true) on a Mongoid model - commonly when resuming an interrupted reindex job or when scripts always pass resume: true after a failure.

Common situations: Recovering a large interrupted reindex on a Mongoid app; copy-pasting resume flows from ActiveRecord-based projects; automation that passes resume: true unconditionally.

Related errors


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