bblimke/webmock · error · RuntimeError

times(N) accepts integers >= 1 only

Error message

times(N) accepts integers >= 1 only

What it means

RequestStub#times(number) makes the most recently declared response sequence repeat number times. It raises a plain RuntimeError unless number is an Integer >= 1 - zero, negative integers, floats, numeric strings and nil are all rejected. The guard keeps the repeat counter from silently no-op'ing when a computed count goes bad.

Source

Thrown at lib/webmock/request_stub.rb:99

        WebMock::Response.new
      elsif @responses_sequences.length > 1
        @responses_sequences.shift if @responses_sequences.first.end?
        @responses_sequences.first.next_response
      else
        @responses_sequences[0].next_response
      end
    end

    def has_responses?
      !@responses_sequences.empty?
    end

    def then
      self
    end

    def times(number)
      raise "times(N) accepts integers >= 1 only" if !number.is_a?(Integer) || number < 1
      if @responses_sequences.empty?
        raise "Invalid WebMock stub declaration." +
          " times(N) can be declared only after response declaration."
      end
      @responses_sequences.last.times_to_repeat += number-1
      self
    end

    def matches?(request_signature)
      self.request_pattern.matches?(request_signature)
    end

    def to_s
      self.request_pattern.to_s
    end

    def self.from_request_signature(signature)
      stub = self.new(signature.method.to_sym, signature.uri.to_s)

View on GitHub (pinned to b187df8827)

Solutions

  1. Pass a literal Integer >= 1: .times(3)
  2. Coerce external input at the boundary: .times(Integer(count)) so bad values fail with a clear ArgumentError
  3. If the intent is zero responses, do not register the stub at all, or rely on the default responses instead

Example fix

// before
stub_request(:get, 'www.example.com').to(body: 'ok').times(ENV.fetch('STUB_TIMES', 1))
# ENV values are Strings -> RuntimeError: times(N) accepts integers >= 1 only

// after
stub_request(:get, 'www.example.com').to(body: 'ok').times(Integer(ENV.fetch('STUB_TIMES', 1)))
Defensive patterns

Strategy: validation

Validate before calling

count = Integer(ENV.fetch('STUB_TIMES', 1)) # raises early on non-numeric input
raise ArgumentError, 'times count must be >= 1' unless count >= 1
stub_request(:get, 'www.example.com').to(body: 'ok').times(count)

Type guard

def valid_times_arg?(value)
  value.is_a?(Integer) && value >= 1
end

Prevention

When it happens

Trigger: .to(body: 'ok').times(0) or .times(-1); .times(2.0) (float from a calculation); .times('3') (string from ENV or YAML config); .times(nil) (optional variable never set); loop-generated stubs where the computed count hits zero.

Common situations: ENV-driven stub counts arriving as strings; Float division or averaging producing non-Integers; refactors that assumed times(0) means never respond; counts taken from let() variables that can be nil.

Related errors


AI-assisted analysis of bblimke/webmock@b187df8827 (2026-08-23). Data as JSON: /api/errors/707667b4291baa4e. Report an issue: GitHub.