{"record":{"id":"a36e1360d3083e2b","repo":"ruby-concurrency/concurrent-ruby","slug":"can-t-set-a-timeout-if-non-block-is-enabled","errorCode":null,"errorMessage":"can't set a timeout if non_block is enabled","messagePattern":"can't set a timeout if non_block is enabled","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby/concurrent/collection/ruby_timeout_queue.rb","lineNumber":28,"sourceCode":"\n        super(*args)\n\n        @mutex = Mutex.new\n        @cond_var = ConditionVariable.new\n      end\n\n      def push(obj)\n        @mutex.synchronize do\n          super(obj)\n          @cond_var.signal\n        end\n      end\n      alias_method :enq, :push\n      alias_method :<<, :push\n\n      def pop(non_block = false, timeout: nil)\n        if non_block && timeout\n          raise ArgumentError, \"can't set a timeout if non_block is enabled\"\n        end\n\n        if non_block\n          super(true)\n        elsif timeout\n          @mutex.synchronize do\n            deadline = Concurrent.monotonic_time + timeout\n            while (now = Concurrent.monotonic_time) < deadline && empty?\n              @cond_var.wait(@mutex, deadline - now)\n            end\n            begin\n              return super(true)\n            rescue ThreadError\n              # still empty\n              nil\n            end\n          end\n        else","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby/concurrent/collection/ruby_timeout_queue.rb#L10-L46","documentation":"`Concurrent::TimeoutQueue#pop(non_block = false, timeout: nil)` (RubyTimeoutQueue backs TimeoutQueue on Ruby < 3.2) supports three modes: blocking pop, non-blocking `pop(true)` (raises ThreadError 'queue empty' when empty), and timed pop via the `timeout:` keyword (returns nil on expiry). A non-blocking call cannot honour a timeout, so passing both `non_block = true` and `timeout:` raises ArgumentError before any dequeue is attempted.","triggerScenarios":"`queue.pop(true, timeout: 5)`; adapters porting ::Queue's `pop(non_block)` signature that also forward a `timeout:` keyword; wrappers that always specify `timeout:` and pass through the caller's `non_block` flag. Legal: `pop`, `pop(true)`, `pop(timeout: 5)`, `pop(false, timeout: 5)`.","commonSituations":"Porting code between ::Queue and Concurrent::TimeoutQueue; generic queue gateway objects that combine both options; cargo-culted `pop(true, timeout: x)` copied from another library's API where the combination is legal.","solutions":["Pick one mode: `queue.pop(timeout: 5)` for a bounded wait, or `queue.pop(true)` for try-now.","In adapters, translate explicitly: `timeout ? q.pop(timeout: timeout) : q.pop(non_block)`.","Model the three modes (block / try / timed) as separate methods in your wrapper so callers cannot combine flags."],"exampleFix":"// before\nitem = queue.pop(true, timeout: 5) # ArgumentError\n\n// after\nitem = queue.pop(timeout: 5) # wait up to 5s, nil on timeout\n// or\nitem = queue.pop(true) # non-blocking, ThreadError when empty","handlingStrategy":"validation","validationCode":"def pop_from(queue, non_block: false, timeout: nil)\n  raise ArgumentError, 'non_block and timeout are mutually exclusive' if non_block && timeout\n  timeout ? queue.pop(timeout: timeout) : queue.pop(non_block)\nend","typeGuard":null,"tryCatchPattern":"begin\n  queue.pop(true, timeout: t)\nrescue ArgumentError\n  queue.pop(timeout: t) # degrade to the timed form\nend","preventionTips":["Model three modes explicitly — blocking, try-now, timed — and never combine try with timed.","Normalize pop signatures inside one queue adapter.","Remember: pop(true) on empty raises ThreadError; timed pop returns nil on expiry."],"tags":["concurrent-ruby","timeout-queue","queue","argumenterror"],"backgroundTag":"mutually-exclusive-arguments","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}