{"record":{"id":"dc147c288b9d9282","repo":"ruby-concurrency/concurrent-ruby","slug":"only-one-of-block-or-value-can-be-supplied","errorCode":null,"errorMessage":"only one of block or value can be supplied","messagePattern":"only one of block or value can be supplied","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby-edge/concurrent/edge/erlang_actor.rb","lineNumber":758,"sourceCode":"      end\n\n      def pid\n        @Pid\n      end\n\n      def traps?\n        @trap\n      end\n\n      def trap(value = true)\n        old = @trap\n        # noinspection RubySimplifyBooleanInspection\n        @trap = !!value\n        old\n      end\n\n      def on(matcher, value = nil, &block)\n        raise ArgumentError, 'only one of block or value can be supplied' if block && value\n        [matcher, value || block]\n      end\n\n      def receive(*rules, timeout: nil, timeout_value: nil, **options, &block)\n        raise NotImplementedError\n      end\n\n      def link(pid)\n        return true if pid == @Pid\n        if @Linked.add? pid\n          pid.tell Link.new(@Pid)\n          if pid.terminated.resolved?\n            # no race since it only could get NoActor\n            if @trap\n              tell Terminate.new pid, NoActor.new(pid)\n            else\n              @Linked.delete pid\n              raise NoActor.new(pid)","sourceCodeStart":740,"sourceCodeEnd":776,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby-edge/concurrent/edge/erlang_actor.rb#L740-L776","documentation":"Inside an ErlangActor Environment, `on(matcher, value = nil, &block)` builds one receive rule: a matcher paired with either an inline reply value (returned when the matcher hits) or a handler block. `value || block` picks the handler, so supplying both a truthy positional value and a block is ambiguous and raises ArgumentError immediately. Note that `nil` as the value with a block is fine — only a truthy second argument plus a block conflicts.","triggerScenarios":"`env.on(Ping, :pong) { |msg| :pong }` — both a constant reply symbol and a block. Wrappers that always capture a block via `&block` and also forward a caller-supplied value: `on(matcher, user_value, &user_block)`. Legal: `on(Ping, :pong)` or `on(Ping) { |msg| ... }` or `on(Ping, nil, &blk)`.","commonSituations":"Refactoring a value-style rule into a computed block (or vice versa) and leaving the old argument in place; DSLs around `receive` that blindly forward both forms; copy-pasted examples mixing the two styles.","solutions":["Delete the positional value and keep the block when the reply must be computed: `on(matcher) { |m| ... }`.","Or delete the block and keep the constant reply: `on(matcher, :stop)`.","In wrapper code, forward only the winner: `on(matcher, block ? nil : value, &block)`.","Standardize your codebase on one style per rule to keep receive tables scannable."],"exampleFix":"// before\nreceive on(Ping, :pong) { |msg| :pong }\n\n// after\nreceive on(Ping, :pong)\n// or\nreceive on(Ping) { |msg| :pong }","handlingStrategy":"validation","validationCode":"def rule(matcher, value = nil, &block)\n  raise ArgumentError, 'pass either a value or a block, not both' if value && block\n  on(matcher, value, &block)\nend","typeGuard":null,"tryCatchPattern":"begin\n  env.on(matcher, value, &blk)\nrescue ArgumentError\n  env.on(matcher, &blk) # prefer the block, drop the value\nend","preventionTips":["Pick one style per rule: constant reply or handler block.","Remember nil is treated as absent — on(m, nil, &blk) is legal.","Keep receive-table builders in helpers that enforce the either/or contract."],"tags":["concurrent-ruby","concurrent-ruby-edge","erlang-actor","receive","argumenterror"],"backgroundTag":"mutually-exclusive-arguments","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}