{"record":{"id":"74911aa8ae6b484e","repo":"ruby-concurrency/concurrent-ruby","slug":"cannot-give-arguments-and-a-block","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_notify_observer_set.rb","lineNumber":99,"sourceCode":"        @observers = {}\n      end\n\n      private\n\n      def duplicate_and_clear_observers\n        synchronize do\n          observers = @observers.dup\n          @observers.clear\n          observers\n        end\n      end\n\n      def duplicate_observers\n        synchronize { @observers.dup }\n      end\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    end\n  end\nend\n","sourceCodeStart":81,"sourceCodeEnd":108,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb#L81-L108","documentation":"notify_to delivers a notification to a set of registered observers in CopyOnNotifyObserverSet. It accepts either a fixed argument list (the same args delivered to every observer) or a block (args recomputed per observer via yield), never both — mixing them would leave the delivered arguments ambiguous, so it raises ArgumentError. This is an extension point, typically hit by custom notification strategies or direct calls to the observer set.","triggerScenarios":"`observer_set.notify_to(observers, :changed, 42) { compute_args }`; custom Observable subclasses whose notify wrappers forward both *args and a block into notify_to.","commonSituations":"Decorator or middleware layers that blindly forward *args and &block; copying notification code from another set implementation that also passes positional args.","solutions":["Pass either the args or the block: `notify_to(observers, :changed, 42)` or `notify_to(observers) { per_observer_args }`.","In forwarding wrappers, branch explicitly: `block ? notify_to(obs, &block) : notify_to(obs, *args)`."],"exampleFix":"// before\nset.notify_to(observers, :changed, payload) { fresh_payload }\n\n// after\nset.notify_to(observers, :changed, payload)\n// or\nset.notify_to(observers) { fresh_payload }","handlingStrategy":"validation","validationCode":"if block_given?\n  set.notify_to(observers) { yield }\nelse\n  set.notify_to(observers, *args)\nend","typeGuard":null,"tryCatchPattern":"begin\n  set.notify_to(observers, :changed, payload) { fresh }\nrescue ArgumentError => e\n  raise unless e.message == 'cannot give arguments and a block'\n  set.notify_to(observers, :changed, payload)\nend","preventionTips":["Decide per notification whether args are fixed (positional) or per-observer (block); never forward both.","Branch on block_given? in any wrapper that delegates to notify_to.","Treat notify_to as an extension point — prefer the set's public notify/notify_and_delete_for surface."],"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"}