Skip to content

fix(openai-compatible): handle reused tool call index from Ollama#14277

Open
CPIDLE wants to merge 1 commit into
vercel:mainfrom
CPIDLE:fix/openai-compatible-tool-call-index
Open

fix(openai-compatible): handle reused tool call index from Ollama#14277
CPIDLE wants to merge 1 commit into
vercel:mainfrom
CPIDLE:fix/openai-compatible-tool-call-index

Conversation

@CPIDLE
Copy link
Copy Markdown

@CPIDLE CPIDLE commented Apr 9, 2026

Summary

  • Fix streaming parser to handle providers (Ollama) that reuse index: 0 for all tool calls in a single response
  • Add test case for parallel tool calls with reused indices

Problem

Ollama's OpenAI-compatible streaming API sends all tool calls with index: 0 instead of incrementing (0, 1, 2...). This causes the @ai-sdk/openai-compatible streaming parser to either:

  1. Skip the 2nd+ tool calls (when the first has already hasFinished)
  2. Merge their arguments into the first call (corrupting the JSON)

This results in a 100% failure rate on any task requiring multiple tool calls in one response.

Verified with: Ollama 0.20.2/0.20.4, models: qwen3-coder:30b, gemma4:e4b, qwen2.5-coder:7b

Ollama issue: ollama/ollama#15457

Fix

When toolCalls[index] is already occupied by a different tool call (different id), treat the incoming delta as a new tool call by assigning index = toolCalls.length.

This is backwards-compatible: providers that send correct indices are unaffected since the id will match the existing entry.

Test plan

  • Added test: should handle parallel tool calls with reused index (Ollama bug)
  • Verified with real Ollama streaming: dual-file write goes from 0/12 to 12/12 pass
  • Existing parallel tool call tests still pass (correct indices unaffected)

Ollama's OpenAI-compatible streaming API sends all tool calls with
`index: 0` instead of incrementing indices (0, 1, 2...). This causes
the streaming parser to silently drop the 2nd+ tool calls or merge
their arguments into the first one.

Fix: when the `toolCalls[index]` slot is already occupied by a
different tool call (different `id`), treat the incoming delta as a
new tool call by assigning it `index = toolCalls.length`.

This is backwards-compatible: providers that send correct indices
are unaffected since the `id` check will match.

Tested with Ollama 0.20.x + qwen3-coder:30b, gemma4:e4b — dual
tool call tasks go from 0% to 100% pass rate.

Ref: ollama/ollama#15457

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tigent tigent Bot added ai/provider related to a provider package. Must be assigned together with at least one `provider/*` label bug Something isn't working as documented provider/openai-compatible Issues related to the @ai-sdk/openai-compatible provider labels Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai/provider related to a provider package. Must be assigned together with at least one `provider/*` label bug Something isn't working as documented provider/openai-compatible Issues related to the @ai-sdk/openai-compatible provider

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant