{"record":{"id":"8a596231e03ed078","repo":"ruby/ruby","slug":"multiple-proxy-options-specified","errorCode":null,"errorMessage":"multiple proxy options specified","messagePattern":"multiple proxy options specified","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/open-uri.rb","lineNumber":191,"sourceCode":"      ensure\n        if io.respond_to? :close!\n          io.close! # Tempfile\n        else\n          io.close if !io.closed?\n        end\n      end\n    else\n      io\n    end\n  end\n\n  def OpenURI.open_loop(uri, options) # :nodoc:\n    proxy_opts = []\n    proxy_opts << :proxy_http_basic_authentication if options.include? :proxy_http_basic_authentication\n    proxy_opts << :proxy if options.include? :proxy\n    proxy_opts.compact!\n    if 1 < proxy_opts.length\n      raise ArgumentError, \"multiple proxy options specified\"\n    end\n    case proxy_opts.first\n    when :proxy_http_basic_authentication\n      opt_proxy, proxy_user, proxy_pass = options.fetch(:proxy_http_basic_authentication)\n      proxy_user = proxy_user.to_str\n      proxy_pass = proxy_pass.to_str\n      if opt_proxy == true\n        raise ArgumentError.new(\"Invalid authenticated proxy option: #{options[:proxy_http_basic_authentication].inspect}\")\n      end\n    when :proxy\n      opt_proxy = options.fetch(:proxy)\n      proxy_user = nil\n      proxy_pass = nil\n    when nil\n      opt_proxy = true\n      proxy_user = nil\n      proxy_pass = nil\n    end","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/lib/open-uri.rb#L173-L209","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Keep exactly one proxy option; drop the other key from the merged hash before calling URI.open","For authenticated proxies, use only :proxy_http_basic_authentication: [URI('http://proxy:8080'), user, pass]","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')"],"exampleFix":"# before\nURI.open(url,\n  proxy: ENV['http_proxy'],\n  proxy_http_basic_authentication: [URI('http://proxy:8080'), 'u', 'p'])\n# => ArgumentError: multiple proxy options specified\n\n# after\nURI.open(url, proxy: URI('http://u:p@proxy:8080'))","handlingStrategy":"validation","validationCode":"proxy_keys = %i[proxy proxy_http_basic_authentication].count { |k| options.include?(k) }\nraise ArgumentError, 'multiple proxy options specified' if proxy_keys > 1\nURI.open(url, **options)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Choose one proxy mechanism for the whole app; embed credentials in the proxy URI if you use :proxy","When merging option hashes from multiple layers, resolve proxy config last and keep a single key","Delete the unused proxy key rather than letting it ride along in defaults"],"tags":["open-uri","ruby","argumenterror","proxy","mutually-exclusive-options"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}