ruby-concurrency/concurrent-ruby · error · ArgumentError
cannot enqueue nil
Error message
cannot enqueue nil
What it means
This is the pure-Ruby heap engine used by Concurrent::PriorityQueue on non-JRuby platforms. As with the Java variant, nil is the queue's 'empty' sentinel (pop returns nil when the heap is exhausted), so push rejects nil items with ArgumentError to keep a stored nil distinguishable from an empty queue.
Source
Thrown at lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb:79
empty? ? nil : @queue[1]
end
# @!macro priority_queue_method_pop
def pop
return nil if empty?
max = @queue[1]
swap(1, @length)
@length -= 1
sink(1)
@queue.pop
max
end
alias_method :deq, :pop
alias_method :shift, :pop
# @!macro priority_queue_method_push
def push(item)
raise ArgumentError.new('cannot enqueue nil') if item.nil?
@length += 1
@queue << item
swim(@length)
true
end
alias_method :<<, :push
alias_method :enq, :push
# @!macro priority_queue_method_from_list
def self.from_list(list, opts = {})
queue = new(opts)
list.each{|item| queue << item }
queue
end
private
# Exchange the values at the given indexes within the internal array.View on GitHub (pinned to 0b88d5ff75)
Solutions
- Skip or filter nils before enqueueing: `items.compact.each { |i| queue << i }`.
- Substitute a real default via fetch for values destined for the queue.
- Use a null-object sentinel (with <=> defined) or a wrapper Struct when 'absent' must be queued.
- Remember items must be mutually comparable anyway — validate comparability along with non-nilness.
Example fix
// before
items.each { |i| queue << i } # i is nil for missing entries -> ArgumentError
// after
items.compact.each { |i| queue << i } Defensive patterns
Strategy: validation
Validate before calling
items.compact.each { |i| queue << i } Type guard
def enqueueable?(item) !item.nil? && item.respond_to?(:<=>) end
Try / catch
begin
queue << item
rescue ArgumentError => e
raise unless e.message == 'cannot enqueue nil'
logger.warn('skipped nil item')
end Prevention
- Filter nils at ingestion, not at enqueue time under load.
- Use fetch(key, default) or a null-object sentinel for absent values.
- Validate comparability of queued items once at the boundary, since the heap requires <=>.
When it happens
Trigger: `queue.push(nil)`, `queue << nil`, `queue.enq(nil)`; `queue << record[:deadline]` where the field is absent; from_list over an array containing nils.
Common situations: Optional or missing values from config, APIs, or database rows flowing into a scheduling queue; nil used as a placeholder for 'not yet computed'; skipping #compact on bulk input.
Related errors
- cannot enqueue nil
- unbuffered channels cannot have a capacity
- capacity must be at least 1 for this buffer type
- no block given
- size must be greater than 0
AI-assisted analysis of ruby-concurrency/concurrent-ruby@0b88d5ff75 (2026-08-21).
Data as JSON: /api/errors/fbc5d34ef5226835.
Report an issue: GitHub.