ruby-concurrency/concurrent-ruby · error · ArgumentError
cannot give arguments and a block
Error message
cannot give arguments and a block
What it means
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.
Source
Thrown at lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb:99
@observers = {}
end
private
def duplicate_and_clear_observers
synchronize do
observers = @observers.dup
@observers.clear
observers
end
end
def duplicate_observers
synchronize { @observers.dup }
end
def notify_to(observers, *args)
raise ArgumentError.new('cannot give arguments and a block') if block_given? && !args.empty?
observers.each do |observer, function|
args = yield if block_given?
observer.send(function, *args)
end
end
end
end
end
View on GitHub (pinned to 0b88d5ff75)
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)`.
Example fix
// before
set.notify_to(observers, :changed, payload) { fresh_payload }
// after
set.notify_to(observers, :changed, payload)
// or
set.notify_to(observers) { fresh_payload } Defensive patterns
Strategy: validation
Validate before calling
if block_given?
set.notify_to(observers) { yield }
else
set.notify_to(observers, *args)
end Try / catch
begin
set.notify_to(observers, :changed, payload) { fresh }
rescue ArgumentError => e
raise unless e.message == 'cannot give arguments and a block'
set.notify_to(observers, :changed, payload)
end Prevention
- 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.
When it happens
Trigger: `observer_set.notify_to(observers, :changed, 42) { compute_args }`; custom Observable subclasses whose notify wrappers forward both *args and a block into notify_to.
Common situations: Decorator or middleware layers that blindly forward *args and █ copying notification code from another set implementation that also passes positional args.
Related errors
- cannot give arguments and a block
- cannot provide both an observer and a block
- cannot provide both an observer and a block
- should pass observer as a first argument or block
- should pass observer as a first argument or block
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/74911aa8ae6b484e.
Report an issue: GitHub.