{"record":{"id":"246448ec2efdb4ad","repo":"jnunemaker/httparty","slug":"timeout-type-must-be-an-integer-or-float","errorCode":null,"errorMessage":"#{ timeout_type } must be an integer or float","messagePattern":"#(.+?) must be an integer or float","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/httparty.rb","lineNumber":611,"sourceCode":"    end\n\n    def unlock(path, options = {}, &block)\n      perform_request Net::HTTP::Unlock, path, options, &block\n    end\n\n    def build_request(http_method, path, options = {})\n      options = ModuleInheritableAttributes.hash_deep_dup(default_options).merge(options)\n      HeadersProcessor.new(headers, options).call\n      process_cookies(options)\n      Request.new(http_method, path, options)\n    end\n\n    attr_reader :default_options\n\n    private\n\n    def validate_timeout_argument(timeout_type, value)\n      raise ArgumentError, \"#{ timeout_type } must be an integer or float\" unless value && (value.is_a?(Integer) || value.is_a?(Float))\n    end\n\n    def ensure_method_maintained_across_redirects(options)\n      unless options.key?(:maintain_method_across_redirects)\n        options[:maintain_method_across_redirects] = true\n      end\n    end\n\n    def perform_request(http_method, path, options, &block) #:nodoc:\n      build_request(http_method, path, options).perform(&block)\n    end\n\n    def process_cookies(options) #:nodoc:\n      return unless options[:cookies] || default_cookies.any?\n      options[:headers] ||= headers.dup\n      options[:headers]['cookie'] = cookies.merge(options.delete(:cookies) || {}).to_cookie_string\n    end\n","sourceCodeStart":593,"sourceCodeEnd":629,"githubUrl":"https://github.com/jnunemaker/httparty/blob/8f4a09e343b94de9f934f388028ca97620c9b378/lib/httparty.rb#L593-L629","documentation":"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.","triggerScenarios":"`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.","commonSituations":"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.","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)`."],"exampleFix":"# before\ndefault_timeout ENV['HTTP_TIMEOUT']   # \"30\" or nil -> ArgumentError\n\n# after\ndefault_timeout (ENV['HTTP_TIMEOUT'] || 10).to_f","handlingStrategy":"validation","validationCode":"def numeric_timeout!(name, v)\n  raise ArgumentError, \"#{name} must be Numeric\" unless v.is_a?(Numeric)\n  v\nend\ndefault_timeout numeric_timeout!(:timeout, (ENV['HTTP_TIMEOUT'] || 10).to_f)","typeGuard":"numeric = ->(v) { v.is_a?(Integer) || v.is_a?(Float) }","tryCatchPattern":"begin\n  default_timeout value\nrescue ArgumentError\n  raise ConfigError, 'cast ENV/YAML timeouts with .to_f before passing them in'\nend","preventionTips":["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."],"tags":["ruby","httparty","configuration","validation","argument-error","timeout"],"backgroundTag":"invalid-timeout-value","analyzedSha":"8f4a09e343b94de9f934f388028ca97620c9b378","analyzedAt":"2026-08-21T19:30:42.003Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}