ankane/searchkick · error · Searchkick::Error

Safety check failed - only run one Model.reindex per model a

Error message

Safety check failed - only run one Model.reindex per model at a time

What it means

Models declaring a reindex queue (searchkick queue_name: 'search') push ids through Searchkick::ReindexQueue, which talks to Redis. Its constructor raises Error 'Searchkick.redis not set' unless Searchkick.redis was assigned beforehand - normally done in config/initializers/searchkick.rb.

Source

Thrown at lib/searchkick/index.rb:447

      else
        index.refresh
        true
      end
    rescue => e
      if Searchkick.transport_error?(e) && (e.message.include?("No handler for type [text]") || e.message.include?("class java.util.ArrayList cannot be cast to class java.util.Map"))
        raise UnsupportedVersionError
      end

      raise e
    end

    # safety check
    # still a chance for race condition since its called before promotion
    # ideal is for user to disable automatic index creation
    # https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#index-creation
    def check_uuid(old_uuid, new_uuid)
      if old_uuid != new_uuid
        raise Error, "Safety check failed - only run one Model.reindex per model at a time"
      end
    end

    def notify(record, name)
      if Searchkick.callbacks_value == :bulk
        yield
      else
        name = "#{record.class.searchkick_klass.name} #{name}" if record && record.class.searchkick_klass
        event = {
          name: name,
          id: search_id(record)
        }
        ActiveSupport::Notifications.instrument("request.searchkick", event) do
          yield
        end
      end
    end

View on GitHub (pinned to 93e901a75b)

Solutions

  1. Set the client in config/initializers/searchkick.rb: Searchkick.redis = Redis.new(url: ENV['REDIS_URL'])
  2. Verify it loaded in every environment that touches the model: rails runner 'p Searchkick.redis'
  3. Ensure the env var / credentials the initializer reads are actually present in that environment

Example fix

# before
# config/initializers/searchkick.rb - missing or empty
class Product < ApplicationRecord
  searchkick queue_name: 'search'
end
Product.save # => Searchkick::Error: Searchkick.redis not set

# after
# config/initializers/searchkick.rb
Searchkick.redis = Redis.new(url: ENV['REDIS_URL'])
Defensive patterns

Strategy: validation

Validate before calling

# config/initializers/searchkick.rb
Searchkick.redis = Redis.new(url: ENV.fetch('REDIS_URL'))

# boot check where queue_name is used
raise 'Searchkick.redis not configured' if Searchkick.redis.nil?

Try / catch

begin
  record.save!
rescue Searchkick::Error => e
  raise unless e.message == 'Searchkick.redis not set'
  Rails.logger.error('search queue disabled: redis not configured')
end

Prevention

When it happens

Trigger: A model with searchkick queue_name: 'search' plus any save/update/reindex, while Searchkick.redis = Redis.new was never set - initializer not created, an env-specific initializer skipped, or a boot path (rake task, engine, test) that does not load initializers.

Common situations: Adding queue-based reindexing per the README but forgetting the redis initializer; Redis config gated behind an env var that is absent in staging/test; multiple apps sharing a model where only one sets Searchkick.redis.

Related errors


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