ankane/searchkick · error · ArgumentError

Unknown stemmer: #{stemmer[:type]}

Error message

Unknown stemmer: #{stemmer[:type]}

What it means

Searchkick's `update_stemming` builds the index analysis chain and only accepts one stemmer type: `"hunspell"`. Any other value in `searchkick stemmer: {type: ...}` falls through the case statement and raises `ArgumentError` at index-options build time (i.e. when creating or reindexing the index). The comment in the source notes that snowball/porter_stemmer could be supported, but they are not implemented in this version.

Source

Thrown at lib/searchkick/index_options.rb:312

            type: language
          },
          searchkick_search2: {
            type: language
          }
        )
      end
    end

    def update_stemming(settings)
      if options[:stemmer]
        stemmer = options[:stemmer]
        # could also support snowball and stemmer
        case stemmer[:type]
        when "hunspell"
          # supports all token filter options
          settings[:analysis][:filter][:searchkick_stemmer] = stemmer
        else
          raise ArgumentError, "Unknown stemmer: #{stemmer[:type]}"
        end
      end

      stem = options[:stem]

      # language analyzer used
      stem = false if settings[:analysis][:analyzer][default_analyzer][:type] != "custom"

      if stem == false
        settings[:analysis][:filter].delete(:searchkick_stemmer)
        settings[:analysis][:analyzer].each do |_, analyzer|
          analyzer[:filter].delete("searchkick_stemmer") if analyzer[:filter]
        end
      end

      if options[:stemmer_override]
        stemmer_override = {
          type: "stemmer_override"

View on GitHub (pinned to 93e901a75b)

Solutions

  1. Use the supported type: `searchkick stemmer: {type: "hunspell", locale: "en_US"}` with a hunspell dictionary installed on the search server.
  2. If you just want standard language stemming, drop `stemmer:` entirely and use `searchkick language: "English"` (or set `stem_exclusion:`/`stemmer_override:` for fine-tuning).
  3. If you truly need snowball, build the analysis chain yourself via the `settings:`/`mappings:` options with `merge_mappings`, bypassing `stemmer:`.
  4. Upgrade searchkick and re-check lib/searchkick/index_options.rb — newer versions may add snowball support (the source comment flags it as a possible addition).

Example fix

# before
class Product < ApplicationRecord
  searchkick stemmer: {type: "snowball", language: "English"}
end
Product.reindex # => ArgumentError: Unknown stemmer: snowball

# after
class Product < ApplicationRecord
  searchkick language: "English", stem_exclusion: ["sku"]
end
Product.reindex
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_STEMMERS = %w[hunspell].freeze

stemmer = {type: "hunspell", locale: "en_US"}
raise ArgumentError, "searchkick supports only: #{SUPPORTED_STEMMERS.join(', ')}" unless SUPPORTED_STEMMERS.include?(stemmer[:type])
class Product < ApplicationRecord
  searchkick stemmer: stemmer
end

Type guard

def searchkick_stemmer_supported?(stemmer)
  stemmer.is_a?(Hash) && %w[hunspell].include?(stemmer[:type])
end

Prevention

When it happens

Trigger: Calling `searchkick stemmer: {type: "snowball", language: "English"}` (or `porter_stemmer`, `kstem`, or any string other than `"hunspell"`) on a model, then running `Model.reindex` or any operation that builds index settings (create index, import).

Common situations: Copying a snowball/kstem config from a raw Elasticsearch tutorial or a different gem (e.g. chewy) into searchkick's `stemmer` option; upgrading searchkick and assuming generic token-filter options pass through; typo'ing the type string. Also hitting this after trying to combine `language:` with a custom stemmer.

Related errors


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