{"record":{"id":"a8569a8059ef8ba2","repo":"jnunemaker/httparty","slug":"basic-auth-must-be-a-hash","errorCode":null,"errorMessage":":basic_auth must be a hash","messagePattern":":basic_auth must be a hash","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/httparty/request.rb","lineNumber":419,"sourceCode":"      options[:headers] ||= {}\n      options[:headers]['Cookie'] = cookies_hash.to_cookie_string\n    end\n\n    # Uses the HTTP Content-Type header to determine the format of the\n    # response It compares the MIME type returned to the types stored in the\n    # SupportedFormats hash\n    def format_from_mimetype(mimetype)\n      if mimetype && parser.respond_to?(:format_from_mimetype)\n        parser.format_from_mimetype(mimetype)\n      end\n    end\n\n    def validate\n      raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0\n      raise ArgumentError, 'only get, post, patch, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method)\n      raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].respond_to?(:to_hash)\n      raise ArgumentError, 'only one authentication method, :basic_auth or :digest_auth may be used at a time' if options[:basic_auth] && options[:digest_auth]\n      raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].respond_to?(:to_hash)\n      raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].respond_to?(:to_hash)\n      raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].respond_to?(:to_hash)\n    end\n\n    def post?\n      Net::HTTP::Post == http_method\n    end\n\n    def set_basic_auth_from_uri\n      if path.userinfo\n        username, password = path.userinfo.split(':')\n        options[:basic_auth] = {username: username, password: password}\n        @credentials_sent = true\n      end\n    end\n\n    def decompress(body, encoding)\n      Decompressor.new(body, encoding).decompress","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/jnunemaker/httparty/blob/8f4a09e343b94de9f934f388028ca97620c9b378/lib/httparty/request.rb#L401-L437","documentation":"Request#validate raises ArgumentError ':basic_auth must be a hash' when options[:basic_auth] is truthy but does not respond to #to_hash. basic_auth is accepted as a keyword option on any verb call and must be a Hash with :username/:password (or 'username'/'password') keys; strings, arrays or auth objects from other libraries are rejected before the request runs.","triggerScenarios":"`Foo.get(url, basic_auth: 'user:pass')`, `basic_auth: [user, pass]`, or `basic_auth: SomeGem::Credentials.new` (an object without to_hash).","commonSituations":"Pasting 'user:pass' strings from curl examples, storing credentials as arrays/tuples in config, and adapting code from gems with different auth option shapes.","solutions":["Pass the documented Hash: `basic_auth: { username: user, password: pass }`.","Convert string creds: `basic_auth: Hash[%w[username password].zip(creds.split(':'))]`.","Prefer the class-level DSL `basic_auth user, pass` for static credentials."],"exampleFix":"# before\nFoo.get(url, basic_auth: 'user:pass')   # String -> ArgumentError\n\n# after\nFoo.get(url, basic_auth: { username: 'user', password: 'pass' })","handlingStrategy":"validation","validationCode":"auth = { username: user, password: pass } unless auth.respond_to?(:to_hash)\nraise ArgumentError, ':basic_auth must be a hash' unless auth.respond_to?(:to_hash)\nFoo.get(url, basic_auth: auth)","typeGuard":"hash_like = ->(v) { v.respond_to?(:to_hash) }","tryCatchPattern":"begin\n  Foo.get(url, basic_auth: auth)\nrescue ArgumentError => e\n  raise unless e.message.include?('basic_auth')\n  Foo.get(url, basic_auth: { username: auth[0], password: auth[1] })\nend","preventionTips":["Always use { username:, password: } literal shape for auth options.","Normalize credentials at the config layer into a Hash with symbol keys.","Prefer class-level `basic_auth user, pass` for static creds."],"tags":["ruby","httparty","validation","argument-error","authentication","basic-auth","request-options"],"backgroundTag":"invalid-argument-type","analyzedSha":"8f4a09e343b94de9f934f388028ca97620c9b378","analyzedAt":"2026-08-21T19:30:42.003Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}