{"record":{"id":"129fb646bffd6e1a","repo":"ruby-concurrency/concurrent-ruby","slug":"cannot-give-arguments-and-a-block-129fb6","errorCode":null,"errorMessage":"cannot give arguments and a block","messagePattern":"cannot give arguments and a block","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb","lineNumber":87,"sourceCode":"      #\n      # @param [Object] args arguments to be passed to each observer\n      # @return [CopyOnWriteObserverSet] self\n      def notify_and_delete_observers(*args, &block)\n        old = clear_observers_and_return_old\n        notify_to(old, *args, &block)\n        self\n      end\n\n      protected\n\n      def ns_initialize\n        @observers = {}\n      end\n\n      private\n\n      def notify_to(observers, *args)\n        raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty?\n        observers.each do |observer, function|\n          args = yield if block_given?\n          observer.send(function, *args)\n        end\n      end\n\n      def observers\n        synchronize { @observers }\n      end\n\n      def observers=(new_set)\n        synchronize { @observers = new_set }\n      end\n\n      def clear_observers_and_return_old\n        synchronize do\n          old_observers = @observers\n          @observers = {}","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb#L69-L105","documentation":"The copy-on-write observer set's notify_to delivers notifications to a set of observers and accepts either a fixed argument list or a block that recomputes args per observer — passing both is ambiguous and raises ArgumentError. Unlike the copy-on-notify variant this method is private, so it is reached through subclasses of the set, custom Observable implementations, or explicit send(:notify_to, ...).","triggerScenarios":"A subclass of CopyOnWriteObserverSet (or Observable code reusing it) calling `notify_to(observers, :changed, data) { block }`; forwarding wrappers that pass both *args and &block into the private notify_to via send.","commonSituations":"Custom notification strategies subclassing one of the observer sets; refactoring notify plumbing from the copy-on-notify set into the copy-on-write set without dropping one of the two forms.","solutions":["Pass either positional args or the block, never both: `notify_to(observers, :changed, data)` or `notify_to(observers) { args }`.","In forwarding code, branch on block_given? before delegating."],"exampleFix":"// before\nset.send(:notify_to, observers, :changed, payload) { fresh_payload }\n\n// after\nset.send(:notify_to, observers, :changed, payload)\n// or\nset.send(:notify_to, observers) { fresh_payload }","handlingStrategy":"validation","validationCode":"if block_given?\n  set.send(:notify_to, observers) { yield }\nelse\n  set.send(:notify_to, observers, *args)\nend","typeGuard":null,"tryCatchPattern":"begin\n  set.send(:notify_to, observers, :changed, payload) { fresh }\nrescue ArgumentError => e\n  raise unless e.message == 'cannot give arguments and a block'\n  set.send(:notify_to, observers, :changed, payload)\nend","preventionTips":["notify_to is private on this set — subclass or use send deliberately, and never pass args plus a block together.","Branch on block_given? before delegating to the private API.","Prefer the set's public notify methods over reaching into notify_to."],"tags":["concurrent-ruby","observer","notify","argumenterror"],"backgroundTag":"callback-arguments-conflict","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}