{"record":{"id":"770adab9e0c2ed17","repo":"vcr/vcr","slug":"vcr-use-cassette-requires-a-block-if-you-cannot","errorCode":null,"errorMessage":"`VCR.use_cassette` requires a block. If you cannot wrap your code in a block, use `VCR.insert_cassette` / `VCR.eject_cassette` instead.","messagePattern":"`VCR\\.use_cassette` requires a block\\. If you cannot wrap your code in a block, use `VCR\\.insert_cassette` / `VCR\\.eject_cassette` instead\\.","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/vcr.rb","lineNumber":186,"sourceCode":"  # block, and ejects the cassette.\n  #\n  # @example\n  #   VCR.use_cassette('twitter', record: :new_episodes) do\n  #     # make an HTTP request\n  #   end\n  #\n  # @param (see #insert_cassette)\n  # @option (see #insert_cassette)\n  # @yield Block to run while this cassette is in use.\n  # @yieldparam cassette [(optional) VCR::Cassette] the cassette that has\n  #  been inserted.\n  # @raise (see #insert_cassette)\n  # @return [void]\n  # @see #insert_cassette\n  # @see #eject_cassette\n  def use_cassette(name, options = {}, &block)\n    unless block\n      raise ArgumentError, \"`VCR.use_cassette` requires a block. \" +\n                           \"If you cannot wrap your code in a block, use \" +\n                           \"`VCR.insert_cassette` / `VCR.eject_cassette` instead.\"\n    end\n\n    cassette = insert_cassette(name, options)\n\n    begin\n      call_block(block, cassette)\n    rescue StandardError\n      cassette.run_failed!\n      raise\n    ensure\n      eject_cassette\n    end\n  end\n\n  # Inserts multiple cassettes the given names\n  #","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/vcr/vcr/blob/a747bb6478674c71f189454083c3cf276f09042c/lib/vcr.rb#L168-L204","documentation":"VCR.use_cassette is a block-scoped API: it inserts a cassette, runs the block, and ejects in an ensure clause. Called without a block it raises ArgumentError pointing you to VCR.insert_cassette / VCR.eject_cassette for non-block use cases (lib/vcr.rb:186).","triggerScenarios":"VCR.use_cassette('api') with no do...end (forgotten or removed in a refactor); expecting the cassette to stay active for the rest of the file; passing a lambda in the options hash instead of as the actual block, e.g. VCR.use_cassette('api', &nil) or VCR.use_cassette('api', block_as_option: proc { }); multiline calls where the do keyword was accidentally deleted.","commonSituations":"Refactors that extracted the body into a helper without forwarding the block (&block); developers wanting a file-wide cassette; copy-paste from examples that used insert/eject style; rspec metadata-based cassette usage mixed with manual calls.","solutions":["Add the block: VCR.use_cassette('api') do ... end","If the code cannot be wrapped in a block (e.g. cassette must span helper methods or setup/teardown), switch to the explicit API: cassette = VCR.insert_cassette('api') ... VCR.eject_cassette","If a helper wraps use_cassette, forward the caller's block with &block"],"exampleFix":"# before\nVCR.use_cassette('api')\nclient.get('/repos') # ArgumentError, and never recorded\n\n# after\nVCR.use_cassette('api') do\n  client.get('/repos')\nend\n\n# non-block alternative\ncassette = VCR.insert_cassette('api')\nclient.get('/repos')\nVCR.eject_cassette","handlingStrategy":"validation","validationCode":"def with_cassette(name, options = {}, &block)\n  raise ArgumentError, 'a block is required' unless block\n  VCR.use_cassette(name, options, &block)\nend","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat use_cassette as strictly block-scoped; for setup/teardown flows use insert_cassette/eject_cassette pairs in before/after hooks","When wrapping use_cassette in helpers, always accept and forward &block"],"tags":["vcr","use-cassette","missing-block","api-misuse","ruby"],"backgroundTag":"missing-block-argument","analyzedSha":"a747bb6478674c71f189454083c3cf276f09042c","analyzedAt":"2026-08-21T19:21:22.610Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}