{"record":{"id":"529b6cf9eb0378d7","repo":"ruby-concurrency/concurrent-ruby","slug":"size-must-be-greater-than-0","errorCode":null,"errorMessage":"size must be greater than 0","messagePattern":"size must be greater than 0","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/concurrent-ruby-edge/concurrent/channel/buffer/buffered.rb","lineNumber":89,"sourceCode":"        def poll\n          synchronize do\n            if ns_empty?\n              Concurrent::NULL\n            else\n              buffer.shift\n            end\n          end\n        end\n\n        private\n\n        # @!macro channel_buffer_initialize\n        #\n        # @param [Integer] size the maximum capacity of the buffer; must be\n        #   greater than zero.\n        # @raise [ArgumentError] when the size is zero (0) or less.\n        def ns_initialize(size)\n          raise ArgumentError.new('size must be greater than 0') if size.to_i <= 0\n          self.capacity = size.to_i\n          self.buffer = []\n        end\n\n        # @!macro channel_buffer_size_reader\n        def ns_size\n          buffer.size\n        end\n\n        # @!macro channel_buffer_empty_question\n        def ns_empty?\n          ns_size == 0\n        end\n\n        # @!macro channel_buffer_full_question\n        def ns_full?\n          ns_size == capacity\n        end","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/ruby-concurrency/concurrent-ruby/blob/0b88d5ff75f69b3740c8f0868e76f833cb2fd45d/lib/concurrent-ruby-edge/concurrent/channel/buffer/buffered.rb#L71-L107","documentation":"Concurrent::Channel::Buffer::Buffered is the bounded FIFO buffer behind buffered channels. Its ns_initialize coerces size with to_i and requires the result to be positive, because a bounded queue with zero or negative capacity cannot exist; 0.5.to_i == 0, so fractional sizes also raise. Note that Channel.new(buffer: :buffered, capacity: 0) never reaches this - channel.rb maps that combination to an unbuffered buffer; direct Buffer construction has no such mapping.","triggerScenarios":"Concurrent::Channel::Buffer::Buffered.new(0), .new(-1), or .new(0.5); also building channels by injecting a raw buffer (Channel.new(some_buffer)) where the buffer was constructed with a config-derived size that is 0 or nil.","commonSituations":"Capacity from ENV/config whose default converts to 0 when missing (ENV.fetch('QUEUE_SIZE', 0).to_i); reusing a capacity constant that was set to 0 to mean 'unbounded'; tests constructing buffers with placeholder sizes.","solutions":["Pass a positive integer size: Concurrent::Channel::Buffer::Buffered.new(10).","Default and validate config-derived sizes before construction, failing loudly at startup rather than deep in a worker thread.","For zero-capacity rendezvous semantics use Buffer::Unbuffered (or an unbuffered Channel)."],"exampleFix":"# before\nbuffer = Concurrent::Channel::Buffer::Buffered.new(ENV.fetch('QUEUE_SIZE', 0).to_i)\n\n# after\nsize = ENV.fetch('QUEUE_SIZE', 1).to_i\nraise ArgumentError, 'QUEUE_SIZE must be >= 1' if size < 1\nbuffer = Concurrent::Channel::Buffer::Buffered.new(size)","handlingStrategy":"validation","validationCode":"size = Integer(size_param)\nraise ArgumentError, 'buffer size must be >= 1' if size < 1\nbuffer = Concurrent::Channel::Buffer::Buffered.new(size)","typeGuard":null,"tryCatchPattern":"begin\n  buffer = Concurrent::Channel::Buffer::Buffered.new(size)\nrescue ArgumentError => e\n  raise ConfigError, \"bad buffer size #{size.inspect}: #{e.message}\"\nend","preventionTips":["to_i runs first: 0.5 and nil-adjacent values collapse to 0 and raise - validate the original value.","Default size keys to 1 (or fail) in config loading; never let 0 mean unbounded.","Prefer Channel.new(buffer: :buffered, capacity: n) over raw Buffer objects unless you need injection."],"tags":["ruby","concurrent-ruby","channel","buffer","argumenterror","capacity"],"backgroundTag":"channel-buffer-misconfiguration","analyzedSha":"0b88d5ff75f69b3740c8f0868e76f833cb2fd45d","analyzedAt":"2026-08-21T20:12:56.291Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}