ankane/searchkick · error · ArgumentError

unknown keywords: #{unknown_keywords.join(", ")}

Error message

unknown keywords: #{unknown_keywords.join(", ")}

What it means

The `searchkick` class macro validates its keyword arguments against a hardcoded allow-list (`:batch_size, :callbacks, :index_name, :knn, :language, ...` and ~45 more). Any key not on the list means you misspelled an option, passed a query-time option at model level, or used an option from a newer/older searchkick version — the unknown keys are collected and reported in one `ArgumentError` at class-load (boot) time.

Source

Thrown at lib/searchkick/model.rb:19

module Searchkick
  module Model
    def searchkick(**options)
      options = Searchkick.model_options.deep_merge(options)

      if options[:conversions]
        Searchkick.warn("The `conversions` option is deprecated in favor of `conversions_v2`, which provides much better search performance. Upgrade to `conversions_v2` or rename `conversions` to `conversions_v1`")
      end

      if options.key?(:conversions_v1)
        options[:conversions] = options.delete(:conversions_v1)
      end

      unknown_keywords = options.keys - [:_all, :_type, :batch_size, :callbacks, :callback_options, :case_sensitive, :conversions, :conversions_v2, :deep_paging, :default_fields,
        :filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :inheritance, :job_options, :knn, :language,
        :locations, :mappings, :match, :max_result_window, :merge_mappings, :routing, :searchable, :search_synonyms, :settings, :similarity,
        :special_characters, :stem, :stemmer, :stem_conversions, :stem_exclusion, :stemmer_override, :suggest, :synonyms, :text_end,
        :text_middle, :text_start, :unscope, :word, :word_end, :word_middle, :word_start]
      raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?

      raise "Only call searchkick once per model" if respond_to?(:searchkick_index)

      Searchkick.models << self

      options[:_type] ||= -> { searchkick_index.klass_document_type(self, true) }
      options[:class_name] = model_name.name

      callbacks = options.key?(:callbacks) ? options[:callbacks] : :inline
      unless [:inline, true, false, :async, :queue].include?(callbacks)
        raise ArgumentError, "Invalid value for callbacks"
      end
      callback_options = (options[:callback_options] || {}).dup
      callback_options[:if] = [-> { Searchkick.callbacks?(default: callbacks) }, callback_options[:if]].compact.flatten(1)

      base = self

      mod = Module.new

View on GitHub (pinned to 93e901a75b)

Solutions

  1. Read the listed keys and fix each typo against the allow-list in lib/searchkick/model.rb:13-16.
  2. Move query-time options (`where`, `order`, `limit`, `per_page`, `fields`, `misspellings`, ...) out of the `searchkick` macro — they belong in `Model.search(...)` calls.
  3. Check `Searchkick::VERSION` and the README section for your gem version to confirm the option exists; pin your Gemfile to the version whose docs you read.
  4. After fixing, run a one-off boot (`rails runner 'puts Product'`) in CI so bad options fail the build, not production.

Example fix

# before
class Product < ApplicationRecord
  searchkick index_name: "products", feilds: [:name], per_page: 20
end # => ArgumentError: unknown keywords: feilds, per_page

# after
class Product < ApplicationRecord
  searchkick index_name: "products", searchable: [:name]
end
Product.search("milk", per_page: 20)
Defensive patterns

Strategy: validation

Validate before calling

# Fail at boot with your own message instead of the raw ArgumentError
MODEL_OPTIONS = %i[index_name searchable filterable language callbacks batch_size knn].freeze
opts = {index_name: "products", searchable: %i[name]}
unknown = opts.keys - MODEL_OPTIONS
raise ArgumentError, "bad searchkick options: #{unknown.join(', ')}" if unknown.any?
class Product < ApplicationRecord
  searchkick **opts
end

Type guard

def valid_searchkick_options?(opts)
  allowed = %i[_all _type batch_size callbacks callback_options case_sensitive conversions conversions_v2 deep_paging default_fields filterable geo_shape highlight ignore_above index_name index_prefix inheritance job_options knn language locations mappings match max_result_window merge_mappings routing searchable search_synonyms settings similarity special_characters stem stemmer stem_conversions stem_exclusion stemmer_override suggest synonyms text_end text_middle text_start unscope word word_end word_middle word_start]
  (opts.keys - allowed).empty?
end

Prevention

When it happens

Trigger: `searchkick feilds: [...]` (typo), `searchkick where: {...}` or `searchkick per_page: 20` (query-time options used at model level), or `searchkick scope_name: :foo` / any option added in a different searchkick version. Raises the moment the model class is loaded.

Common situations: Upgrading/downgrading the gem: an option that exists in v5 but not v4 (or vice versa) kills the app at boot; copying a config snippet from README HEAD while running an older gem; muscle-memory from other gems (elasticsearch-model, chewy) whose option names differ; silent Ruby behavior where a misspelled keyword becomes an unknown key rather than a syntax error.

Related errors


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