ruby/ruby · error · ArgumentError

multiple proxy options specified

Error message

multiple proxy options specified

What it means

OpenURI.open_loop builds proxy settings from the options hash and allows at most one proxy selector: :proxy or :proxy_http_basic_authentication. If both keys are present it raises ArgumentError 'multiple proxy options specified' because the two mechanisms would fight over which proxy (and whose credentials) to use.

Source

Thrown at lib/open-uri.rb:191

      ensure
        if io.respond_to? :close!
          io.close! # Tempfile
        else
          io.close if !io.closed?
        end
      end
    else
      io
    end
  end

  def OpenURI.open_loop(uri, options) # :nodoc:
    proxy_opts = []
    proxy_opts << :proxy_http_basic_authentication if options.include? :proxy_http_basic_authentication
    proxy_opts << :proxy if options.include? :proxy
    proxy_opts.compact!
    if 1 < proxy_opts.length
      raise ArgumentError, "multiple proxy options specified"
    end
    case proxy_opts.first
    when :proxy_http_basic_authentication
      opt_proxy, proxy_user, proxy_pass = options.fetch(:proxy_http_basic_authentication)
      proxy_user = proxy_user.to_str
      proxy_pass = proxy_pass.to_str
      if opt_proxy == true
        raise ArgumentError.new("Invalid authenticated proxy option: #{options[:proxy_http_basic_authentication].inspect}")
      end
    when :proxy
      opt_proxy = options.fetch(:proxy)
      proxy_user = nil
      proxy_pass = nil
    when nil
      opt_proxy = true
      proxy_user = nil
      proxy_pass = nil
    end

View on GitHub (pinned to 0e5b888e1c)

Solutions

  1. Keep exactly one proxy option; drop the other key from the merged hash before calling URI.open
  2. For authenticated proxies, use only :proxy_http_basic_authentication: [URI('http://proxy:8080'), user, pass]
  3. Or embed credentials in the proxy URI passed to :proxy — open-uri parses proxy userinfo (proxy_uri.userinfo.split(':')) — e.g. proxy: URI('http://user:pass@proxy:8080')

Example fix

# before
URI.open(url,
  proxy: ENV['http_proxy'],
  proxy_http_basic_authentication: [URI('http://proxy:8080'), 'u', 'p'])
# => ArgumentError: multiple proxy options specified

# after
URI.open(url, proxy: URI('http://u:p@proxy:8080'))
Defensive patterns

Strategy: validation

Validate before calling

proxy_keys = %i[proxy proxy_http_basic_authentication].count { |k| options.include?(k) }
raise ArgumentError, 'multiple proxy options specified' if proxy_keys > 1
URI.open(url, **options)

Prevention

When it happens

Trigger: URI.open(url, proxy: ENV['http_proxy'], proxy_http_basic_authentication: [proxy_uri, user, pass]). Gem/application layers each merging their own proxy config into one options hash; env-based proxy detection combined with explicit authenticated-proxy credentials.

Common situations: A library auto-detects ENV['http_proxy'] via :proxy while application code also passes authenticated proxy credentials; layered HTTP wrappers deep-merging default options with call options, both sides adding a proxy key.

Related errors


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/8a596231e03ed078. Report an issue: GitHub.