bblimke/webmock · error · ArgumentError
#with method invoked with no arguments. Either options hash
Error message
#with method invoked with no arguments. Either options hash or block must be specified. Created a block with do..end? Try creating it with curly braces {} instead. What it means
RequestPattern#with must receive either a non-empty options hash (body, headers, query, basic_auth) or a block; with an empty hash and no block the call is ambiguous, so webmock raises ArgumentError immediately (lib/webmock/request_pattern.rb:29). The do..end hint is about Ruby block precedence: in a longer chain a do..end block can bind to a different method than intended, leaving with() with no block at all, while curly braces bind to the nearest method. An options hash built at runtime can also collapse to {} when every conditional entry is skipped.
Source
Thrown at lib/webmock/request_pattern.rb:29
matcher.class.name =~ /R?Spec::Mocks::ArgumentMatchers::HashExcludingMatcher/
end
end
class RequestPattern
attr_reader :method_pattern, :uri_pattern, :body_pattern, :headers_pattern
def initialize(method, uri, options = {})
@method_pattern = MethodPattern.new(method)
@uri_pattern = create_uri_pattern(uri)
@body_pattern = nil
@headers_pattern = nil
@with_block = nil
assign_options(options)
end
def with(options = {}, &block)
raise ArgumentError.new('#with method invoked with no arguments. Either options hash or block must be specified. Created a block with do..end? Try creating it with curly braces {} instead.') if options.empty? && !block_given?
assign_options(options)
@with_block = block
self
end
def matches?(request_signature)
content_type = request_signature.headers['Content-Type'] if request_signature.headers
content_type = content_type.split(';').first if content_type
@method_pattern.matches?(request_signature.method) &&
@uri_pattern.matches?(request_signature.uri) &&
(@body_pattern.nil? || @body_pattern.matches?(request_signature.body, content_type || "")) &&
(@headers_pattern.nil? || @headers_pattern.matches?(request_signature.headers)) &&
(@with_block.nil? || @with_block.call(request_signature))
end
def to_s
string = "#{@method_pattern.to_s.upcase}".dup
string << " #{@uri_pattern.to_s}"View on GitHub (pinned to b187df8827)
Solutions
- Give with at least one real constraint: .with(body: {...}), .with(headers: {...}) or .with(query: {...})
- Or express the constraint as a block with curly braces: .with { |req| req.body.include?('token') }
- If no narrowing is needed, remove the .with call entirely - stub_request(:get, url) already matches method and URI
- For dynamic options, only chain with when the hash is non-empty: stub = a_request(:get, url); stub = stub.with(opts) unless opts.empty?
Example fix
# before
opts = {}
opts[:query] = { page: 2 } if paginated
stub_request(:get, 'https://api.example.com/items').with(opts) # ArgumentError when paginated is false
# after
opts = {}
opts[:query] = { page: 2 } if paginated
stub = stub_request(:get, 'https://api.example.com/items')
stub = stub.with(opts) unless opts.empty? Defensive patterns
Strategy: validation
Validate before calling
# Helper that never calls .with with empty options:
def apply_with(stub, opts = {}, &blk)
opts.empty? && blk.nil? ? stub : stub.with(opts, &blk)
end
stub = apply_with(stub_request(:get, url), conditional_opts) Prevention
- Default helper parameters to nil instead of {} and branch on presence
- Prefer curly-brace blocks with .when chaining methods
- In shared examples, raise a clear error yourself when a forwarded with: hash arrives empty
When it happens
Trigger: Calling .with({}) or .with() with no arguments. Building options dynamically (opts = {}; opts[:body] = b if condition; stub_request(:get, url).with(opts)) when the condition is false so opts stays empty. Attaching the constraint block with do..end to the wrong method of a chain so with() receives neither options nor a block. Shared examples that forward an optional with: hash that defaults to {}
Common situations: Shared stub helpers that accept an optional options hash and forward it blindly; refactoring that moves a body/headers constraint into a conditional branch; copy-pasting README block examples but using do..end inside a bigger method chain; a typo like .with(body:) where the value on the next line is an empty hash.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- The basic_auth option value should be an array which contain
- WebMock does not support matching body for multipart/form-da
- Wrong order. Use :before_local_stubs or :after_local_stubs
- Unknown key: #{k.inspect}. Valid keys are: #{valid_keys.map(
- Invalid notation. Must be one of: [:flat, :dot, :subscript,
AI-assisted analysis of bblimke/webmock@b187df8827 (2026-08-23).
Data as JSON: /api/errors/f955bcfc6a1e1126.
Report an issue: GitHub.