Description
When streaming responses from the Anthropic API, build_chunk occasionally receives a non-Hash value (e.g. true) instead of the expected Hash, causing:
NoMethodError: undefined method 'dig' for true
ruby_llm-1.13.1/lib/ruby_llm/providers/anthropic/streaming.rb:15:in 'build_chunk'
ruby_llm-1.13.1/lib/ruby_llm/streaming.rb:33:in 'block in handle_stream'
ruby_llm-1.13.1/lib/ruby_llm/streaming.rb:97:in 'block in handle_sse'
Root Cause
handle_data in streaming.rb:102 parses the SSE event data with JSON.parse(data). When Anthropic's stream emits a bare JSON true (or any other non-Hash JSON value), the guard on line 104 correctly identifies it's not a Hash error payload and returns it as-is:
def handle_data(data, env)
parsed = JSON.parse(data)
return parsed unless parsed.is_a?(Hash) && parsed.key?('error')
# ...
end
This non-Hash value propagates up through handle_sse (line 97) → handle_stream (line 33), where build_chunk(data) is called. Since build_chunk assumes data is a Hash and calls data.dig('delta', 'type'), it crashes.
Suggested Fix
Guard against non-Hash data in handle_stream:
def handle_stream(&block)
build_on_data_handler do |data|
block.call(build_chunk(data)) if data.is_a?(Hash)
end
end
The current check is if data, which passes for true. Tightening it to data.is_a?(Hash) safely skips non-Hash values (heartbeats, keep-alives, or unexpected payloads) that no provider's build_chunk can handle.
Version
ruby_llm 1.13.1
Description
When streaming responses from the Anthropic API,
build_chunkoccasionally receives a non-Hash value (e.g.true) instead of the expected Hash, causing:Root Cause
handle_datainstreaming.rb:102parses the SSE event data withJSON.parse(data). When Anthropic's stream emits a bare JSONtrue(or any other non-Hash JSON value), the guard on line 104 correctly identifies it's not a Hash error payload and returns it as-is:This non-Hash value propagates up through
handle_sse(line 97) →handle_stream(line 33), wherebuild_chunk(data)is called. Sincebuild_chunkassumesdatais a Hash and callsdata.dig('delta', 'type'), it crashes.Suggested Fix
Guard against non-Hash data in
handle_stream:The current check is
if data, which passes fortrue. Tightening it todata.is_a?(Hash)safely skips non-Hash values (heartbeats, keep-alives, or unexpected payloads) that no provider'sbuild_chunkcan handle.Version
ruby_llm 1.13.1