{"record":{"id":"f418396e1b6988c5","repo":"ankane/searchkick","slug":"not-sure-how-to-load-records","errorCode":null,"errorMessage":"Not sure how to load records","messagePattern":"Not sure how to load records","errorType":"exception","errorClass":"Searchkick::Error","httpStatus":null,"severity":"error","filePath":"lib/searchkick.rb","lineNumber":296,"sourceCode":"  end\n\n  def self.warn(message)\n    super(\"[searchkick] WARNING: #{message}\")\n  end\n\n  # private\n  def self.load_records(relation, ids)\n    relation =\n      if relation.respond_to?(:primary_key)\n        primary_key = relation.primary_key\n        raise Error, \"Need primary key to load records\" if !primary_key\n\n        relation.where(primary_key => ids)\n      elsif relation.respond_to?(:queryable)\n        relation.queryable.for_ids(ids)\n      end\n\n    raise Error, \"Not sure how to load records\" if !relation\n\n    relation\n  end\n\n  # public (for reindexing conversions)\n  def self.load_model(class_name, allow_child: false)\n    model = class_name.safe_constantize\n    raise Error, \"Could not find class: #{class_name}\" unless model\n    if allow_child\n      unless model.respond_to?(:searchkick_klass)\n        raise Error, \"#{class_name} is not a searchkick model\"\n      end\n    else\n      unless Searchkick.models.include?(model)\n        raise Error, \"#{class_name} is not a searchkick model\"\n      end\n    end\n    model","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/ankane/searchkick/blob/93e901a75b11a25101668a616e006b158251b16e/lib/searchkick.rb#L278-L314","documentation":"method_parameters.ef_search on OpenSearch kNN queries exists only from OpenSearch 2.16 onwards. Before building the query Searchkick checks the live server version (Searchkick.server_below?('2.16.0')) and raises Error 'ef_search requires OpenSearch 2.16+' when the option is used against an older cluster. The check is skipped on Elasticsearch, which takes a different branch.","triggerScenarios":"Product.search('*', knn: {field: :embedding, vector: vec, distance: 'cosine', ef_search: 200}) while Searchkick.client points at OpenSearch < 2.16 (e.g. 2.11, 1.x, or an AWS OpenSearch engine older than 2.16).","commonSituations":"Tuning recall on a local dev instance with a recent OpenSearch image, then deploying to an older managed cluster (AWS OpenSearch <= 2.13 engines); docker-compose pinning an old opensearch image; upgrading Searchkick versions that added the ef_search option.","solutions":["Remove ef_search from the query so the server default applies","Upgrade the OpenSearch cluster/engine to 2.16+ and keep the tuning","Set it conditionally: opts[:ef_search] = 500 unless Searchkick.server_below?('2.16.0')"],"exampleFix":"# before\nProduct.search('*', knn: {field: :v, vector: vec, distance: 'cosine', ef_search: 500})\n# => Searchkick::Error: ef_search requires OpenSearch 2.16+\n\n# after\nknn = {field: :v, vector: vec, distance: 'cosine'}\nknn[:ef_search] = 500 unless Searchkick.server_below?('2.16.0')\nProduct.search('*', knn: knn)","handlingStrategy":"validation","validationCode":"knn = {field: :v, vector: vec, distance: 'cosine'}\nknn[:ef_search] = 500 unless Searchkick.server_below?('2.16.0')\nProduct.search('*', knn: knn)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Gate server-version-dependent options behind a capability check helper in one place","Pin the same OpenSearch version across dev, CI and production (docker-compose, engine versions)","Print Searchkick.server_version at boot and compare against feature requirements"],"tags":["searchkick","opensearch","knn","version-incompatibility","ef-search"],"backgroundTag":"feature-requires-newer-server-version","analyzedSha":"93e901a75b11a25101668a616e006b158251b16e","analyzedAt":"2026-08-21T19:06:23.767Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}