jnunemaker/httparty · error · ArgumentError

#{ timeout_type } must be an integer or float

Error message

#{ timeout_type } must be an integer or float

What it means

The private helper validate_timeout_argument raises ArgumentError when a timeout value is nil or is not an Integer/Float. It is called by the four DSL setters default_timeout, open_timeout, read_timeout and write_timeout, and the method name itself is interpolated into the message via __method__, so the message reads e.g. 'default_timeout must be an integer or float'. The check `value &&` means nil is rejected too, not just wrong types.

Source

Thrown at lib/httparty.rb:611

    end

    def unlock(path, options = {}, &block)
      perform_request Net::HTTP::Unlock, path, options, &block
    end

    def build_request(http_method, path, options = {})
      options = ModuleInheritableAttributes.hash_deep_dup(default_options).merge(options)
      HeadersProcessor.new(headers, options).call
      process_cookies(options)
      Request.new(http_method, path, options)
    end

    attr_reader :default_options

    private

    def validate_timeout_argument(timeout_type, value)
      raise ArgumentError, "#{ timeout_type } must be an integer or float" unless value && (value.is_a?(Integer) || value.is_a?(Float))
    end

    def ensure_method_maintained_across_redirects(options)
      unless options.key?(:maintain_method_across_redirects)
        options[:maintain_method_across_redirects] = true
      end
    end

    def perform_request(http_method, path, options, &block) #:nodoc:
      build_request(http_method, path, options).perform(&block)
    end

    def process_cookies(options) #:nodoc:
      return unless options[:cookies] || default_cookies.any?
      options[:headers] ||= headers.dup
      options[:headers]['cookie'] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string
    end

View on GitHub (pinned to 8f4a09e343)

Solutions

  1. Cast before the call: `default_timeout ENV['TIMEOUT']&.to_f`.
  2. Provide a numeric default: `default_timeout (ENV['TIMEOUT'] || 10).to_f`.
  3. Ensure nil never reaches the setter: `default_timeout cfg.fetch(:timeout, 5)`.

Example fix

# before
default_timeout ENV['HTTP_TIMEOUT']   # "30" or nil -> ArgumentError

# after
default_timeout (ENV['HTTP_TIMEOUT'] || 10).to_f
Defensive patterns

Strategy: validation

Validate before calling

def numeric_timeout!(name, v)
  raise ArgumentError, "#{name} must be Numeric" unless v.is_a?(Numeric)
  v
end
default_timeout numeric_timeout!(:timeout, (ENV['HTTP_TIMEOUT'] || 10).to_f)

Type guard

numeric = ->(v) { v.is_a?(Integer) || v.is_a?(Float) }

Try / catch

begin
  default_timeout value
rescue ArgumentError
  raise ConfigError, 'cast ENV/YAML timeouts with .to_f before passing them in'
end

Prevention

When it happens

Trigger: `default_timeout '30'`, `open_timeout ENV['OPEN_TIMEOUT']` (String or nil), `read_timeout nil`, `write_timeout :ten` inside an HTTParty class. Any value pulled from ENV, YAML, or JSON without casting will hit this at class-load time.

Common situations: Reading timeouts from environment variables or config files that yield strings, forgetting to convert milliseconds to seconds after copying values from another stack, and passing nil when a setting is absent.

Understand the failure class

Related errors


AI-assisted analysis of jnunemaker/httparty@8f4a09e343 (2026-08-21). Data as JSON: /api/errors/246448ec2efdb4ad. Report an issue: GitHub.