{"record":{"id":"3e86fb8235de6031","repo":"lostisland/faraday","slug":"memoized-must-be-called-with-a-block","errorCode":null,"errorMessage":"#memoized must be called with a block","messagePattern":"#memoized must be called with a block","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/faraday/options.rb","lineNumber":172,"sourceCode":"\n    # Internal\n    def self.options(mapping)\n      attribute_options.update(mapping)\n    end\n\n    # Internal\n    def self.options_for(key)\n      attribute_options[key]\n    end\n\n    # Internal\n    def self.attribute_options\n      @attribute_options ||= {}\n    end\n\n    def self.memoized(key, &block)\n      unless block\n        raise ArgumentError, '#memoized must be called with a block'\n      end\n\n      memoized_attributes[key.to_sym] = block\n      class_eval <<-RUBY, __FILE__, __LINE__ + 1\n        remove_method(key) if method_defined?(key, false)\n        def #{key}() self[:#{key}]; end\n      RUBY\n    end\n\n    def self.memoized_attributes\n      @memoized_attributes ||= {}\n    end\n\n    def [](key)\n      key = key.to_sym\n      if (method = self.class.memoized_attributes[key])\n        super || (self[key] = instance_eval(&method))\n      else","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/lostisland/faraday/blob/b25b1b26ccef34b1460b0267115be238ca758087/lib/faraday/options.rb#L154-L190","documentation":"Faraday::Options subclasses (request options, ssl options, proxy options and user-defined ones) get their attribute DSL from two class-level helpers: options(mapping) for plain attributes and memoized(key, &block), which registers a block that computes the attribute's default and uses class_eval to define a reader delegating to self[:key]. The block is mandatory — memoized raises ArgumentError immediately when called without one.","triggerScenarios":"Writing class MyOptions < Faraday::Options and calling memoized :foo with no block; metaprogramming that forwards method names to memoized but drops the block (define_method(name) { memoized(name) } loses the block); copying old option-class code where the default used to be a second positional argument instead of a block.","commonSituations":"Library authors adding custom connection/request option classes; upgrading across Faraday versions where the Options DSL internals changed shape; using send(:memoized, key) which silently drops any block you meant to pass.","solutions":["Always pass the default-value block: memoized(:foo) { 'bar' } — the block's result is stored as memoized_attributes and the reader self[:foo] falls back to it.","If you only need a plain stored attribute with no computed default, use the sibling DSL instead: options foo: :bar.","When forwarding through metaprogramming, forward the block explicitly (define_method(name) { |&blk| memoized(name, &blk) } or use __method__ pass-through), because send drops blocks silently only if you forget &.","Check the Faraday version's options.rb you are writing against — the DSL is marked Internal and its arity has changed between major versions."],"exampleFix":"# before\nclass MyOptions < Faraday::Options\n  memoized :retries   # no block\nend\n# => ArgumentError: #memoized must be called with a block\n\n# after\nclass MyOptions < Faraday::Options\n  memoized(:retries) { 2 }\nend\nMyOptions.from({}).retries # => 2","handlingStrategy":"validation","validationCode":"raise ArgumentError, 'memoized requires a default block' unless block_given?\nmemoized(key, &block)","typeGuard":"null","tryCatchPattern":"begin\n  memoized(key, &block)\nrescue ArgumentError => e\n  raise unless e.message.include?('#memoized')\n  options(key => nil) # degrade to a plain attribute\nend","preventionTips":["Treat Faraday::Options DSL as internal API: pin versions in CI and re-run your options specs on upgrades.","Always pass the default block: memoized(:key) { default_value }.","When forwarding through metaprogramming, forward blocks explicitly with &blk; plain send drops them silently."],"tags":["ruby","faraday","options","dsl","internal-api","argumenterror","metaprogramming"],"backgroundTag":"missing-block-argument","analyzedSha":"b25b1b26ccef34b1460b0267115be238ca758087","analyzedAt":"2026-08-21T19:43:20.220Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}