jnunemaker/httparty · error · ArgumentError
only one authentication method, :basic_auth or :digest_auth
Error message
only one authentication method, :basic_auth or :digest_auth may be used at a time
What it means
Request#validate raises ArgumentError when both options[:basic_auth] and options[:digest_auth] are present on the same request. HTTParty cannot apply two WWW-Authenticate schemes at once and refuses to risk sending credentials computed for the wrong challenge. The conflict can come from a single call or from class-level defaults merging with per-request options.
Source
Thrown at lib/httparty/request.rb:418
options[:headers] ||= {}
options[:headers]['Cookie'] = cookies_hash.to_cookie_string
end
# Uses the HTTP Content-Type header to determine the format of the
# response It compares the MIME type returned to the types stored in the
# SupportedFormats hash
def format_from_mimetype(mimetype)
if mimetype && parser.respond_to?(:format_from_mimetype)
parser.format_from_mimetype(mimetype)
end
end
def validate
raise HTTParty::RedirectionTooDeep.new(last_response), 'HTTP redirects too deep' if options[:limit].to_i <= 0
raise ArgumentError, 'only get, post, patch, put, delete, head, and options methods are supported' unless SupportedHTTPMethods.include?(http_method)
raise ArgumentError, ':headers must be a hash' if options[:headers] && !options[:headers].respond_to?(:to_hash)
raise ArgumentError, 'only one authentication method, :basic_auth or :digest_auth may be used at a time' if options[:basic_auth] && options[:digest_auth]
raise ArgumentError, ':basic_auth must be a hash' if options[:basic_auth] && !options[:basic_auth].respond_to?(:to_hash)
raise ArgumentError, ':digest_auth must be a hash' if options[:digest_auth] && !options[:digest_auth].respond_to?(:to_hash)
raise ArgumentError, ':query must be hash if using HTTP Post' if post? && !options[:query].nil? && !options[:query].respond_to?(:to_hash)
end
def post?
Net::HTTP::Post == http_method
end
def set_basic_auth_from_uri
if path.userinfo
username, password = path.userinfo.split(':')
options[:basic_auth] = {username: username, password: password}
@credentials_sent = true
end
end
def decompress(body, encoding)View on GitHub (pinned to 8f4a09e343)
Solutions
- Use exactly one auth type per request: remove the other key.
- If a base class sets basic_auth, override per-request with `basic_auth: nil`... instead restructure: clear defaults or use separate client classes.
- For endpoints with different schemes, split into two HTTParty classes (one basic, one digest).
Example fix
# before
class Base
include HTTParty
basic_auth 'u', 'p'
end
Base.get(url, digest_auth: { username: 'u', password: 'p' }) # ArgumentError
# after
class BasicClient
include HTTParty
basic_auth 'u', 'p'
end
class DigestClient
include HTTParty
digest_auth 'u', 'p'
end Defensive patterns
Strategy: validation
Validate before calling
raise ArgumentError, 'use only one of basic_auth/digest_auth' if opts.key?(:basic_auth) && opts.key?(:digest_auth) Foo.get(url, **opts)
Try / catch
begin
Foo.get(url, **opts)
rescue ArgumentError => e
raise unless e.message.include?('authentication method')
opts = opts.except(:basic_auth) # or :digest_auth, per target API
retry
end Prevention
- One client class per authentication scheme.
- Audit class-level defaults before adding per-request auth options.
- When switching an API from Basic to Digest, grep the codebase for the old option.
When it happens
Trigger: `Foo.get(url, basic_auth: { username: u, password: p }, digest_auth: { username: u, password: p })`; class-level `basic_auth u, p` combined with a per-request `digest_auth:` option (defaults are deep-merged into request options); credentials extracted from a URI userinfo combined with an explicit digest_auth hash.
Common situations: Switching an API from Basic to Digest auth and leaving the old setting behind, shared client base classes setting basic_auth for all children while one endpoint needs digest, and copying both options from a provider's docs 'to be safe'.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- :basic_auth must be a hash
- :digest_auth must be a hash
- 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
AI-assisted analysis of jnunemaker/httparty@8f4a09e343 (2026-08-21).
Data as JSON: /api/errors/1997da2f770ab9fb.
Report an issue: GitHub.