{"record":{"id":"1bf1bdbf163d7281","repo":"lostisland/faraday","slug":"expected-read-write-open-got-type-inspect","errorCode":null,"errorMessage":"Expected :read, :write, :open. Got #{type.inspect} :(","messagePattern":"Expected :read, :write, :open\\. Got #(.+?) :\\(","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/faraday/adapter.rb","lineNumber":95,"sourceCode":"\n      env.response.finish(env) unless env.parallel? || !finished\n      env.response\n    end\n\n    # Fetches either a read, write, or open timeout setting. Defaults to the\n    # :timeout value if a more specific one is not given.\n    #\n    # @param type [Symbol] Describes which timeout setting to get: :read,\n    #                      :write, or :open.\n    # @param options [Hash] Hash containing Symbol keys like :timeout,\n    #                       :read_timeout, :write_timeout, or :open_timeout\n    #\n    # @return [Integer, nil] Timeout duration in seconds, or nil if no timeout\n    #                        has been set.\n    def request_timeout(type, options)\n      key = TIMEOUT_KEYS.fetch(type) do\n        msg = \"Expected :read, :write, :open. Got #{type.inspect} :(\"\n        raise ArgumentError, msg\n      end\n      options[key] || options[:timeout]\n    end\n  end\nend\n\nrequire 'faraday/adapter/test'\n","sourceCodeStart":77,"sourceCodeEnd":103,"githubUrl":"https://github.com/lostisland/faraday/blob/b25b1b26ccef34b1460b0267115be238ca758087/lib/faraday/adapter.rb#L77-L103","documentation":"Faraday::Adapter#request_timeout resolves which timeout option to use by looking the type up in the frozen TIMEOUT_KEYS map ({ read: :read_timeout, open: :open_timeout, write: :write_timeout }), falling back to the generic :timeout option. The map only accepts the symbols :read, :write and :open; any other value raises ArgumentError. It is mostly an adapter-author-facing API: built-in adapters call it with hardcoded symbols, so end users usually hit it from custom adapters or direct calls.","triggerScenarios":"Calling request_timeout with an unsupported symbol, e.g. request_timeout(:connect, options), request_timeout(:total, ...) or a string like 'read' instead of :read. Writing a custom adapter that copies timeout handling from another HTTP library and reuses its option names (:connect_timeout, :ssl_timeout). A typo such as :wirte or :opne.","commonSituations":"Authoring or maintaining a custom Faraday adapter (the main real-world source); refactoring timeout code and renaming the type symbols; passing a user-supplied configuration string straight through as the type argument instead of normalizing it to a symbol.","solutions":["Pass one of the three supported symbols: :read, :write, or :open (request_timeout(:open, env[:request]) maps to options[:open_timeout] || options[:timeout]).","If the type comes from configuration, normalize it before the call: type = type.to_s.downcase.to_sym and reject values outside the set.","For timeout kinds with no Faraday mapping (e.g. a TLS handshake timeout), read the option directly from the options hash (options[:ssl_timeout]) instead of going through request_timeout.","In custom adapter specs, enumerate the supported types so a renamed symbol fails in CI instead of in production."],"exampleFix":"// before (custom adapter)\ndef call(env)\n  timeout = request_timeout(:connect, env[:request])\n  # => ArgumentError: Expected :read, :write, :open. Got :connect :(\nend\n\n// after\ndef call(env)\n  timeout = request_timeout(:open, env[:request]) # maps to :open_timeout / :timeout\nend","handlingStrategy":"validation","validationCode":"return unless Faraday::Adapter::TIMEOUT_KEYS.key?(type)\ntimeout = adapter.request_timeout(type, options)","typeGuard":"def valid_timeout_type?(type)\n  Faraday::Adapter::TIMEOUT_KEYS.key?(type)\nend","tryCatchPattern":"begin\n  adapter.request_timeout(type, options)\nrescue ArgumentError => e\n  logger.warn(\"unsupported timeout type #{type}: #{e.message}\")\n  options[:timeout] # fall back to the generic timeout\nend","preventionTips":["Use only the symbols :read, :write, :open; they map to :read_timeout/:write_timeout/:open_timeout with :timeout as fallback.","When the type comes from config or user input, whitelist-normalize it: type.to_s.downcase.to_sym then check membership before calling.","In custom adapters, unit-test the timeout branch with all three symbols so renames break CI, not production."],"tags":["ruby","faraday","adapter","timeout","argumenterror","custom-adapter"],"backgroundTag":"invalid-argument-value","analyzedSha":"b25b1b26ccef34b1460b0267115be238ca758087","analyzedAt":"2026-08-21T19:43:20.220Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}