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
- Cast before the call: `default_timeout ENV['TIMEOUT']&.to_f`.
- Provide a numeric default: `default_timeout (ENV['TIMEOUT'] || 10).to_f`.
- 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
- Always cast ENV/config timeouts: `(cfg || 10).to_f`.
- nil is rejected too — default it before the setter sees it.
- Store timeouts in seconds, not milliseconds.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Default params must be an object which responds to #to_hash
- Headers must be an object which responds to #to_hash
- Cookies must be an object which responds to #to_hash
- The URI adapter should respond to #parse
- '#{format.inspect}' Must be one of: #{supported_format_names
AI-assisted analysis of jnunemaker/httparty@8f4a09e343 (2026-08-21).
Data as JSON: /api/errors/246448ec2efdb4ad.
Report an issue: GitHub.