Skip to content

fix(ai): tolerate empty-string tool call id/name in streaming deltas#37783

Closed
Garfier wants to merge 1 commit into
anomalyco:v2from
Garfier:fix-tool-stream-empty-id
Closed

fix(ai): tolerate empty-string tool call id/name in streaming deltas#37783
Garfier wants to merge 1 commit into
anomalyco:v2from
Garfier:fix-tool-stream-empty-id

Conversation

@Garfier

@Garfier Garfier commented Jul 19, 2026

Copy link
Copy Markdown

Problem

Some OpenAI-compatible APIs (e.g. DashScope token-plan / GLM-5.2) send empty strings for id and function.name on subsequent tool call deltas instead of omitting them or sending null:

delta 1: {"id":"call_8c1f...","function":{"name":"calculator","arguments":"{"}}   ✅
delta 2: {"id":"","function":{"name":"","arguments":"\"expression\": "}}          ⚠️ empty string
delta 3: {"id":"","function":{"name":"","arguments":"\"2"}}                       ⚠️ empty string

ToolStream.appendOrStart uses ?? (nullish coalescing) to fall back to accumulated values, but "" is not null/undefined so the fallback never triggers. The subsequent !id check (!""true) then fails with:

OpenAI Chat tool call delta is missing id or name

Fix

Treat empty strings as absent in appendOrStart so the accumulated identity from the first delta is preserved:

- const id = delta.id ?? current?.id
- const name = delta.name ?? current?.name
+ const id = (delta.id || undefined) ?? current?.id
+ const name = (delta.name || undefined) ?? current?.name

Testing

Added test case "tolerates empty-string id and name on subsequent deltas" simulating the DashScope token-plan streaming format. All 8 tests pass.

Verified against the real token-plan API (token-plan.cn-beijing.maas.aliyuncs.com) with GLM-5.2.

Some OpenAI-compatible APIs (e.g. DashScope token-plan / GLM-5.2) send
empty strings for id and function.name on subsequent tool call deltas
instead of omitting them or sending null. The nullish coalescing
operator (??) does not treat empty strings as absent, causing
appendOrStart to fail with 'tool call delta is missing id or name'.

Treat empty strings as absent so the accumulated identity from the
first delta is preserved.
@github-actions

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions github-actions Bot added the needs:compliance This means the issue will auto-close after 2 hours. label Jul 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

This PR doesn't fully meet our contributing guidelines and PR template.

What needs to be fixed:

  • PR description is missing required template sections. Please use the PR template.

Please edit this PR description to address the above within 2 hours, or it will be automatically closed.

If you believe this was flagged incorrectly, please let a maintainer know.

@github-actions

Copy link
Copy Markdown
Contributor

This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 2-hour window.

Feel free to open a new pull request that follows our guidelines.

@github-actions github-actions Bot removed the needs:compliance This means the issue will auto-close after 2 hours. label Jul 19, 2026
@github-actions github-actions Bot closed this Jul 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant