Skip to content

Fix streaming tool call nil arguments#587

Merged
crmne merged 5 commits intocrmne:mainfrom
afurm:fix/streaming-tool-call-nil-args
Mar 1, 2026
Merged

Fix streaming tool call nil arguments#587
crmne merged 5 commits intocrmne:mainfrom
afurm:fix/streaming-tool-call-nil-args

Conversation

@afurm
Copy link
Contributor

@afurm afurm commented Jan 28, 2026

What this does

Fixes a streaming crash when tool-call deltas omit function.arguments by normalizing nil/empty fragments during accumulation, and adds a regression spec to cover the case.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation
  • Performance improvement

Scope check

  • I read the Contributing Guide
  • This aligns with RubyLLM's focus on LLM communication
  • This isn't application-specific logic that belongs in user code
  • This benefits most users, not just my specific use case

Required for new features

  • I opened an issue before writing code and received maintainer approval
  • Linked issue: #___

PRs for new features or enhancements without a prior approved issue will be closed.

Quality check

  • I ran overcommit --install and all hooks pass
  • I tested my changes thoroughly
    • For provider changes: Re-recorded VCR cassettes with bundle exec rake vcr:record[provider_name]
    • All tests pass: bundle exec rspec
  • I updated documentation if needed
  • I didn't modify auto-generated files manually (models.json, aliases.json)

AI-generated code

  • I used AI tools to help write this code
  • I have reviewed and understand all generated code (required if above is checked)

API changes

  • Breaking change
  • New public methods/classes
  • Changed method signatures
  • No API changes

@aka-nez
Copy link

aka-nez commented Feb 4, 2026

Faced exactly the same issue with openrouter provider

@smerickson
Copy link

I had been running into issues using Haiku 4.5 at AWS Bedrock while streaming and using tool calls. The way it manifested was the model calling a tool with incorrect parameters. I always had a sneaking suspicion that it wasn't model hallucination because I had never experienced that when I was using the AWS SDK directly instead of RubyLLM. I just applied this patch to my system and my sreaming issues with Haiku seen to have been resolved. this would be great to get merged into core.

@afurm
Copy link
Contributor Author

afurm commented Feb 4, 2026

Thanks for confirming and for testing this.

@KieranP
Copy link

KieranP commented Feb 7, 2026

Is this error I've just started seeing on local/Ollama related to this PR? I wasn't seeing this about a month ago, maybe a recent Ollama update changed something? If not related, shall I open a new issue?

>
/Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/error.rb:52:in 'RubyLLM::ErrorMiddleware.parse_error': invalid message content type: <nil> (RubyLLM::BadRequestError)
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/streaming.rb:126:in 'RubyLLM::Streaming#handle_parsed_error'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/streaming.rb:86:in 'RubyLLM::Streaming#handle_failed_response'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/streaming.rb:50:in 'block in RubyLLM::Streaming#build_on_data_handler'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/streaming.rb:169:in 'block in RubyLLM::Streaming::FaradayHandlers.v2_on_data'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/options/env.rb:176:in 'block in Faraday::Env#stream_response'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/4.0.0/net/protocol.rb:540:in 'Net::ReadAdapter#call_block'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/4.0.0/net/protocol.rb:531:in 'Net::ReadAdapter#<<'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/4.0.0/net/protocol.rb:172:in 'Net::BufferedIO#read'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http/response.rb:604:in 'block in Net::HTTPResponse#read_body_0'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http/response.rb:589:in 'Net::HTTPResponse#inflater'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http/response.rb:594:in 'Net::HTTPResponse#read_body_0'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http/response.rb:364:in 'Net::HTTPResponse#read_body'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb:116:in 'block (2 levels) in Faraday::Adapter::NetHttp#request_with_wrapped_block'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http.rb:2461:in 'block in Net::HTTP#transport_request'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http/response.rb:321:in 'Net::HTTPResponse#reading_body'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http.rb:2458:in 'Net::HTTP#transport_request'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http.rb:2410:in 'Net::HTTP#request'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb:113:in 'block in Faraday::Adapter::NetHttp#request_with_wrapped_block'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/net-http-0.9.1/lib/net/http.rb:1630:in 'Net::HTTP#start'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb:112:in 'Faraday::Adapter::NetHttp#request_with_wrapped_block'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb:98:in 'block in Faraday::Adapter::NetHttp#perform_request'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/options/env.rb:172:in 'Faraday::Env#stream_response'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb:97:in 'Faraday::Adapter::NetHttp#perform_request'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb:66:in 'block in Faraday::Adapter::NetHttp#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/adapter.rb:45:in 'Faraday::Adapter#connection'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb:65:in 'Faraday::Adapter::NetHttp#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/error.rb:39:in 'RubyLLM::ErrorMiddleware#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/middleware.rb:56:in 'Faraday::Middleware#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/middleware.rb:56:in 'Faraday::Middleware#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-multipart-1.2.0/lib/faraday/multipart/middleware.rb:27:in 'Faraday::Multipart::Middleware#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-retry-2.4.0/lib/faraday/retry/middleware.rb:171:in 'block in Faraday::Retry::Middleware#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-retry-2.4.0/lib/faraday/retry/retryable.rb:7:in 'Faraday::Retryable#with_retries'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-retry-2.4.0/lib/faraday/retry/middleware.rb:167:in 'Faraday::Retry::Middleware#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/middleware.rb:56:in 'Faraday::Middleware#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/response/logger.rb:25:in 'Faraday::Response::Logger#call'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/rack_builder.rb:153:in 'Faraday::RackBuilder#build_response'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/connection.rb:452:in 'Faraday::Connection#run_request'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/faraday-2.14.0/lib/faraday/connection.rb:280:in 'Faraday::Connection#post'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/connection.rb:37:in 'RubyLLM::Connection#post'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/streaming.rb:11:in 'RubyLLM::Streaming#stream_response'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/provider.rb:57:in 'RubyLLM::Provider#complete'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/chat.rb:133:in 'RubyLLM::Chat#complete'
        from /Users/kieran/.asdf/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/ruby_llm-1.11.0/lib/ruby_llm/chat.rb:36:in 'RubyLLM::Chat#ask'
        from 3_query_database.rb:38:in '<main>'

@crmne
Copy link
Owner

crmne commented Mar 1, 2026

Hi @KieranP could you root cause that error to this PR?

@codecov
Copy link

codecov bot commented Mar 1, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.87%. Comparing base (303a4fe) to head (179162f).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #587      +/-   ##
==========================================
+ Coverage   80.85%   80.87%   +0.01%     
==========================================
  Files         113      113              
  Lines        5177     5181       +4     
  Branches     1340     1342       +2     
==========================================
+ Hits         4186     4190       +4     
  Misses        991      991              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@crmne crmne merged commit bdef162 into crmne:main Mar 1, 2026
22 checks passed
@crmne
Copy link
Owner

crmne commented Mar 1, 2026

@KieranP thanks for reporting this. I traced it and it looks separate from #587: this PR fixes nil tool-call arguments in streaming, while your error is in the Ollama assistant message content path (invalid message content type: <nil>). I’m planning a direct fix on main for that path next so we can merge this PR independently.

@crmne
Copy link
Owner

crmne commented Mar 1, 2026

@KieranP fixed in ddc4592

@afurm afurm deleted the fix/streaming-tool-call-nil-args branch March 1, 2026 16:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants