{"record":{"id":"962fe9ed2922f194","repo":"ankane/searchkick","slug":"pass-scroll-option-to-the-search-method-for-scro","errorCode":null,"errorMessage":"Pass `scroll` option to the search method for scrolling","messagePattern":"Pass `scroll` option to the search method for scrolling","errorType":"exception","errorClass":"Searchkick::Error","httpStatus":null,"severity":"error","filePath":"lib/searchkick/results.rb","lineNumber":177,"sourceCode":"\n    def with_score\n      return enum_for(:with_score) unless block_given?\n\n      with_hit.each do |result, hit|\n        yield result, hit[\"_score\"]\n      end\n    end\n\n    def misspellings?\n      @options[:misspellings]\n    end\n\n    def scroll_id\n      @response[\"_scroll_id\"]\n    end\n\n    def scroll\n      raise Error, \"Pass `scroll` option to the search method for scrolling\" unless scroll_id\n\n      if block_given?\n        records = self\n        while records.any?\n          yield records\n          records = records.scroll\n        end\n\n        records.clear_scroll\n      else\n        begin\n          # TODO Active Support notifications for this scroll call\n          params = {\n            scroll: options[:scroll],\n            body: {scroll_id: scroll_id}\n          }\n          Searchkick.add_opaque_id(params, options[:opaque_id]) if options[:opaque_id]\n          Results.new(@klass, Searchkick.client.scroll(params), @options)","sourceCodeStart":159,"sourceCodeEnd":195,"githubUrl":"https://github.com/ankane/searchkick/blob/93e901a75b11a25101668a616e006b158251b16e/lib/searchkick/results.rb#L159-L195","documentation":"Searchkick's Results#scroll raises this when the result set has no scroll cursor. Elasticsearch scroll requires a keep-alive window passed to the original search call; only then does the response include `_scroll_id` (checked at results.rb:172-177). Calling `.scroll` on a query that was issued without the `scroll:` option has no cursor to continue, so Searchkick raises instead of sending an invalid scroll request.","triggerScenarios":"Calling `.scroll` on results of a search that lacked the option, e.g. `Product.search('*').scroll`. Passing `scroll:` as an argument to `.scroll` itself instead of to the `search` method. Copying scroll-iteration code onto a normal paginated search result.","commonSituations":"Adopting scroll for the first time from the Searchkick docs and putting the option on the wrong call; converting existing page/per_page code to scroll iteration; invoking the block form `results.scroll { |batch| ... }` on a non-scroll result.","solutions":["Pass the `scroll:` option to the search method itself: `Product.search('*', scroll: '1m')` - the response then carries `_scroll_id` and `.scroll` works","Use the block form `Product.search('*', scroll: '1m').scroll { |batch| ... }` so batches are drained and the scroll context is cleared automatically","If you only need pages rather than a stable cursor, keep using `page:`/`per_page:` instead of scroll"],"exampleFix":"# before\nresults = Product.search(\"milk\")\nnext_batch = results.scroll # raises: no _scroll_id in the response\n\n# after\nresults = Product.search(\"milk\", scroll: \"1m\")\nnext_batch = results.scroll\n# or let Searchkick drain and clear the cursor:\nProduct.search(\"milk\", scroll: \"1m\").scroll { |batch| process(batch) }","handlingStrategy":"validation","validationCode":"# Route every full-dataset iteration through one helper that always issues the option\ndef search_scroll_all(model, term = \"*\", window: \"1m\", &block)\n  model.search(term, scroll: window).scroll(&block)\nend\n\n# or check the public cursor accessor before scrolling:\nresults = Product.search(\"*\")\nresults.scroll { |b| process(b) } if results.scroll_id","typeGuard":null,"tryCatchPattern":"begin\n  batch = results.scroll\nrescue Searchkick::Error => e\n  raise unless e.message.start_with?(\"Pass `scroll` option\")\n  batch = Product.search(term, scroll: \"1m\") # reissue the search with scrolling enabled\nend","preventionTips":["Always pair intent to iterate the full dataset with `scroll:` on the search call itself","Wrap scroll iteration in a single helper so every scroll search is issued consistently","Check `results.scroll_id` (public, results.rb:172) before calling `.scroll`"],"tags":["searchkick","elasticsearch","scroll","pagination","ruby"],"backgroundTag":"cursor-pagination","analyzedSha":"93e901a75b11a25101668a616e006b158251b16e","analyzedAt":"2026-08-21T19:06:23.767Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}