{"record":{"id":"69332f28a7899de2","repo":"ruby-concurrency/concurrent-ruby","slug":"provide-only-a-value-or-a-block","errorCode":null,"errorMessage":"provide only a value or a block","messagePattern":"provide only a value or a block","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/ivar.rb","lineNumber":64,"sourceCode":"  # 2. For recent application:\n  #    [DataDrivenFuture in Habanero Java from Rice](http://www.cs.rice.edu/~vs3/hjlib/doc/edu/rice/hj/api/HjDataDrivenFuture.html).\n  class IVar < Synchronization::LockableObject\n    include Concern::Obligation\n    include Concern::Observable\n\n    # Create a new `IVar` in the `:pending` state with the (optional) initial value.\n    #\n    # @param [Object] value the initial value\n    # @param [Hash] opts the options to create a message with\n    # @option opts [String] :dup_on_deref (false) call `#dup` before returning\n    #   the data\n    # @option opts [String] :freeze_on_deref (false) call `#freeze` before\n    #   returning the data\n    # @option opts [String] :copy_on_deref (nil) call the given `Proc` passing\n    #   the internal value and returning the value returned from the proc\n    def initialize(value = NULL, opts = {}, &block)\n      if value != NULL && block_given?\n        raise ArgumentError.new('provide only a value or a block')\n      end\n      super(&nil)\n      synchronize { ns_initialize(value, opts, &block) }\n    end\n\n    # Add an observer on this object that will receive notification on update.\n    #\n    # Upon completion the `IVar` will notify all observers in a thread-safe way.\n    # The `func` method of the observer will be called with three arguments: the\n    # `Time` at which the `Future` completed the asynchronous operation, the\n    # final `value` (or `nil` on rejection), and the final `reason` (or `nil` on\n    # fulfillment).\n    #\n    # @param [Object] observer the object that will be notified of changes\n    # @param [Symbol] func symbol naming the method to call when this\n    #   `Observable` has changes`\n    def add_observer(observer = nil, func = :update, &block)\n      raise ArgumentError.new('cannot provide both an observer and a block') if observer && block","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/ivar.rb#L46-L82","documentation":"An IVar is a write-once container that starts pending and is completed exactly once. Its constructor accepts either an initial value or a block that computes the value — never both. Passing a value and a block simultaneously raises ArgumentError 'provide only a value or a block'.","triggerScenarios":"Concurrent::IVar.new(42) { compute } — value plus block; copying an initialization pattern from IVar#set (which also takes value-or-block) into the constructor while keeping both; passing a value that was meant to be an options hash entry.","commonSituations":"Refactors where a computed default was replaced by a literal but the block stayed; mixing :executor-style option hashes with the positional value slot; subclasses calling super with both.","solutions":["Choose one: Concurrent::IVar.new(42) for a known value, or Concurrent::IVar.new { compute } for a deferred one","If you need options, put them in the hash after the value/default: Concurrent::IVar.new { compute } is equivalent to passing opts in many examples — keep the value slot untouched","If both a value and computation exist, decide precedence in your own code and pass only the winner"],"exampleFix":"# before\nivar = Concurrent::IVar.new(42) { expensive_default }\n\n# after\nivar = Concurrent::IVar.new(42)\n# or, when the value must be computed:\nivar = Concurrent::IVar.new { expensive_default }","handlingStrategy":"validation","validationCode":"def build_ivar(value = nil, has_value: false, &block)\n  raise ArgumentError, 'value or block, not both' if has_value && block\n  has_value ? Concurrent::IVar.new(value) : Concurrent::IVar.new(&block)\nend","typeGuard":null,"tryCatchPattern":"begin\n  Concurrent::IVar.new(value) { compute }\nrescue ArgumentError => e\n  raise ArgumentError, 'pick value or block for IVar' if /value or a block/.match?(e.message)\n  raise\nend","preventionTips":["Pick one initialization style (value or block) per codebase and stick to it","Keep constructor positional slot for the value only; everything else goes in the opts hash","Add a lint/review check for IVar.new calls that have both an argument and a brace block"],"tags":["ruby","concurrency","ivar","argument-validation","constructor"],"backgroundTag":"mutually-exclusive-arguments","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}