{"record":{"id":"249398c54b4e9452","repo":"ankane/searchkick","slug":"cannot-reindex-object","errorCode":null,"errorMessage":"Cannot reindex object","messagePattern":"Cannot reindex object","errorType":"exception","errorClass":"Searchkick::Error","httpStatus":null,"severity":"error","filePath":"lib/searchkick/index.rb","lineNumber":225,"sourceCode":"      ReindexQueue.new(name)\n    end\n\n    # reindex\n\n    # note: this is designed to be used internally\n    # so it does not check object matches index class\n    def reindex(object, method_name: nil, ignore_missing: nil, full: false, **options)\n      if @options[:job_options]\n        options[:job_options] = (@options[:job_options] || {}).merge(options[:job_options] || {})\n      end\n\n      if object.is_a?(Array)\n        # note: purposefully skip full\n        return reindex_records(object, method_name: method_name, ignore_missing: ignore_missing, **options)\n      end\n\n      if !object.respond_to?(:searchkick_klass)\n        raise Error, \"Cannot reindex object\"\n      end\n\n      scoped = Searchkick.relation?(object)\n      # call searchkick_klass for inheritance\n      relation = scoped ? object.all : Searchkick.scope(object.searchkick_klass).all\n\n      refresh = options.fetch(:refresh, !scoped)\n      options.delete(:refresh)\n\n      if method_name || (scoped && !full)\n        mode = options.delete(:mode) || :inline\n        scope = options.delete(:scope)\n        job_options = options.delete(:job_options)\n        raise ArgumentError, \"unsupported keywords: #{options.keys.map(&:inspect).join(\", \")}\" if options.any?\n\n        # import only\n        import_scope(relation, method_name: method_name, mode: mode, scope: scope, ignore_missing: ignore_missing, job_options: job_options)\n        self.refresh if refresh","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/ankane/searchkick/blob/93e901a75b11a25101668a616e006b158251b16e/lib/searchkick/index.rb#L207-L243","documentation":"Inside where hashes, field: {op: value} supports a fixed operator set: :in, :exists, :not, and the range comparisons :gt, :gte, :lt, :lte. Any other key raises ArgumentError 'Unknown where operator: ...' with the offending operator inspected, so typos and SQL-style names fail fast at query-build time.","triggerScenarios":"Product.search('*', where: {price: {eq: 5}}), where: {created_at: {after: date}} or where: {status: {ne: 'sold'}}. Valid names are :gt/:gte/:lt/:lte, :in, :exists, :not (plus :_or/:_and/:_not/:_script at the top level).","commonSituations":"Translating SQL or ActiveRecord conditions (eq/ne/like/after/between) to Searchkick; building operator hashes dynamically from user input; typos like :gteq or :greater_than.","solutions":["Use the supported operators: {gt:}, {gte:}, {lt:}, {lte:}, {in: [...]}, {exists: true/false}, {not: ...}","Negation is :not - where: {status: {not: 'sold'}} - not :ne/:not_eq","Validate operator keys against a whitelist when filters are built from user input"],"exampleFix":"# before\nProduct.search('*', where: {price: {gteq: 10, ne: nil}})\n# => ArgumentError: Unknown where operator: :gteq\n\n# after\nProduct.search('*', where: {price: {gte: 10}, status: {not: 'sold'}})","handlingStrategy":"validation","validationCode":"ALLOWED_OPS = %i[in exists not gt gte lt lte].freeze\n\ndef sanitize_where(field_ops)\n  field_ops.slice(*ALLOWED_OPS)\nend\n\nProduct.search('*', where: {price: sanitize_where(params_ops)})","typeGuard":null,"tryCatchPattern":"begin\n  Product.search('*', where: where_filters)\nrescue ArgumentError => e\n  raise unless e.message.start_with?('Unknown where operator')\n  where_filters.transform_keys! { |k| ALIAS[k] || k } # e.g. eq -> gte-less designs; log unknown\n  retry\nend","preventionTips":["Whitelist operator keys when where hashes are built from user or API input","Keep a translation table from your API's filter vocabulary to Searchkick operators","Add a unit test per operator you rely on"],"tags":["searchkick","where","query-operators","argumenterror"],"backgroundTag":"unknown-operator","analyzedSha":"93e901a75b11a25101668a616e006b158251b16e","analyzedAt":"2026-08-21T19:06:23.767Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}