Skip to content

fix(openai, openai-compatible): send null content for tool-only assistant messages#13744

Merged
gr2m merged 3 commits into
mainfrom
josh/fix-null-content-tool-only
Apr 17, 2026
Merged

fix(openai, openai-compatible): send null content for tool-only assistant messages#13744
gr2m merged 3 commits into
mainfrom
josh/fix-null-content-tool-only

Conversation

@dancer

@dancer dancer commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

background

when an assistant message contains only tool-call parts (no text), convertToOpenAICompatibleChatMessages and convertToOpenAIChatMessages send content: "". providers backed by AWS Bedrock reject this with ValidationException: messages: text content blocks must be non-empty

summary

  • change content: text to content: text || null for assistant messages in both @ai-sdk/openai-compatible and @ai-sdk/openai
  • update tests to expect null instead of "" for tool-only assistant messages

checklist

  • tests have been added / updated (for bug fixes / features)
  • documentation has been added / updated (for bug fixes / features)
  • a patch changeset for relevant packages has been added (run pnpm changeset in root)
  • i have reviewed this pull request (self-review)

related issues

fixes #13466

Future work

The same content: text pattern exists in @ai-sdk/xai, @ai-sdk/deepseek, @ai-sdk/groq, and @ai-sdk/mistral and will hit the same Bedrock error under equivalent routing. Tracked separately in #14612.

@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 Issues related to the @ai-sdk/openai provider provider/openai-compatible Issues related to the @ai-sdk/openai-compatible provider labels Mar 23, 2026
@dancer dancer added the backport Admins only: add this label to a pull request in order to backport it to the prior version label Mar 23, 2026

@gr2m gr2m left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same content: text pattern exists unfixed in 4 other providers: xai, deepseek, groq, mistral. If those get routed through Bedrock-backed endpoints, they'll hit the same bug. I created a follow up issue: #14612

@gr2m gr2m merged commit bfb756d into main Apr 17, 2026
18 checks passed
@gr2m gr2m deleted the josh/fix-null-content-tool-only branch April 17, 2026 19:25
ghost pushed a commit that referenced this pull request Apr 17, 2026
…tant messages (#13744)

## background

when an assistant message contains only tool-call parts (no text),
`convertToOpenAICompatibleChatMessages` and
`convertToOpenAIChatMessages` send `content: ""`. providers backed by
AWS Bedrock reject this with `ValidationException: messages: text
content blocks must be non-empty`

## summary

- change `content: text` to `content: text || null` for assistant
messages in both `@ai-sdk/openai-compatible` and `@ai-sdk/openai`
- update tests to expect `null` instead of `""` for tool-only assistant
messages

## checklist

- [x] tests have been added / updated (for bug fixes / features)
- [ ] documentation has been added / updated (for bug fixes / features)
- [x] a _patch_ changeset for relevant packages has been added (run
`pnpm changeset` in root)
- [x] i have reviewed this pull request (self-review)

## Future work

The same `content: text` pattern exists in `@ai-sdk/xai`,
`@ai-sdk/deepseek`, `@ai-sdk/groq`, and `@ai-sdk/mistral` and will hit
the same Bedrock error under equivalent routing. Tracked separately in
#14612.

## related issues

fixes #13466
@ghost ghost removed the backport Admins only: add this label to a pull request in order to backport it to the prior version label Apr 17, 2026
@ghost

ghost commented Apr 17, 2026

Copy link
Copy Markdown

✅ Backport PR created: #14613

aayush-kapoor added a commit that referenced this pull request Apr 17, 2026
## Background

CI was breaking ( a test wasn't updated for some reason ) after this PR
#13744

## Summary

updated snapshot
mvtandas added a commit to mvtandas/ai that referenced this pull request Apr 17, 2026
…sistant messages

When an assistant message contains only tool-call parts (no text),
the converters send content: "". Providers backed by AWS Bedrock
reject this with: ValidationException: messages: text content blocks
must be non-empty.

This applies the same fix from vercel#13744 (openai, openai-compatible)
to the remaining four providers: xai, deepseek, groq, and mistral.

Change: content: text → content: text || null

Fixes vercel#14612
@ghost

ghost commented Apr 17, 2026

Copy link
Copy Markdown

🚀 Published in:

Package Version
ai 7.0.0-beta.111
@ai-sdk/alibaba 2.0.0-beta.33
@ai-sdk/amazon-bedrock 5.0.0-beta.41
@ai-sdk/angular 3.0.0-beta.111
@ai-sdk/anthropic 4.0.0-beta.37
@ai-sdk/assemblyai 3.0.0-beta.28
@ai-sdk/azure 4.0.0-beta.38
@ai-sdk/baseten 2.0.0-beta.31
@ai-sdk/black-forest-labs 2.0.0-beta.27
@ai-sdk/bytedance 2.0.0-beta.28
@ai-sdk/cerebras 3.0.0-beta.31
@ai-sdk/cohere 4.0.0-beta.28
@ai-sdk/deepgram 3.0.0-beta.27
@ai-sdk/deepinfra 3.0.0-beta.31
@ai-sdk/deepseek 3.0.0-beta.29
@ai-sdk/devtools 1.0.0-beta.16
@ai-sdk/elevenlabs 3.0.0-beta.27
@ai-sdk/fal 3.0.0-beta.27
@ai-sdk/fireworks 3.0.0-beta.31
@ai-sdk/gateway 4.0.0-beta.62
@ai-sdk/gladia 3.0.0-beta.27
@ai-sdk/google 4.0.0-beta.45
@ai-sdk/google-vertex 5.0.0-beta.58
@ai-sdk/groq 4.0.0-beta.30
@ai-sdk/huggingface 2.0.0-beta.31
@ai-sdk/hume 3.0.0-beta.27
@ai-sdk/klingai 4.0.0-beta.28
@ai-sdk/langchain 3.0.0-beta.111
@ai-sdk/llamaindex 3.0.0-beta.111
@ai-sdk/lmnt 3.0.0-beta.27
@ai-sdk/luma 3.0.0-beta.27
@ai-sdk/mcp 2.0.0-beta.33
@ai-sdk/mistral 4.0.0-beta.29
@ai-sdk/moonshotai 3.0.0-beta.31
@ai-sdk/open-responses 2.0.0-beta.29
@ai-sdk/openai 4.0.0-beta.38
@ai-sdk/openai-compatible 3.0.0-beta.31
@ai-sdk/otel 1.0.0-beta.57
@ai-sdk/perplexity 4.0.0-beta.30
@ai-sdk/prodia 2.0.0-beta.30
@ai-sdk/provider-utils 5.0.0-beta.26
@ai-sdk/react 4.0.0-beta.111
@ai-sdk/replicate 3.0.0-beta.28
@ai-sdk/revai 3.0.0-beta.28
@ai-sdk/rsc 3.0.0-beta.112
@ai-sdk/svelte 5.0.0-beta.111
@ai-sdk/togetherai 3.0.0-beta.31
@ai-sdk/valibot 3.0.0-beta.26
@ai-sdk/vercel 3.0.0-beta.31
@ai-sdk/voyage 1.0.0-beta.0
@ai-sdk/vue 4.0.0-beta.111
@ai-sdk/workflow 1.0.0-beta.26
@ai-sdk/xai 4.0.0-beta.43

ghost pushed a commit that referenced this pull request Apr 20, 2026
…only assistant messages (#14613)

This is an automated backport of #13744 to the release-v6.0 branch. FYI
@dancer

---------

Co-authored-by: josh <144584931+dancer@users.noreply.github.com>
Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com>
@relayking

relayking commented Apr 30, 2026

Copy link
Copy Markdown

This breaks vanilla openai with "Invalid value for 'content': expected a string, got null" if you happen to have no tool calls and empty text.
Not the end of the world, but not what you would expect from patch release.

cc @dancer

@dancer

dancer commented Apr 30, 2026

Copy link
Copy Markdown
Collaborator Author

@relayking ty for letting me know i'll take a look today

dancer added a commit that referenced this pull request May 4, 2026
…or assistant messages with tool calls (#14951)

## background

backport of #14950 from main to release-v6.0

## related issues

backport of #14950
follow-up to #13744
dancer added a commit that referenced this pull request May 4, 2026
…messages with tool calls (#14950)

## background

#13744 changed `content: text` to `content: text || null` for assistant
messages. this correctly fixed tool-only messages (openai requires
`content: null` when `tool_calls` is present), but also broke the case
where an assistant message has empty text and no tool calls - openai
rejects `content: null` when `tool_calls` is absent with "Invalid value
for 'content': expected a string, got null"

per the [openai api
spec](https://developers.openai.com/api/reference/go/resources/chat/subresources/completions),
content is "required unless `tool_calls` or `function_call` is
specified"

## summary

- only send `null` when `toolCalls.length > 0`, otherwise preserve the
text string
- add regression tests for both `@ai-sdk/openai` and
`@ai-sdk/openai-compatible`

## verification

verified against live openai chat completions api with
`openai.chat('gpt-4o-mini')` - empty assistant content now sends
`content: ""` and returns a valid response

## related issues

follow-up to #13744
Mmartinrusso added a commit to Mmartinrusso/ai that referenced this pull request May 5, 2026
…sistant messages

Follow-up to vercel#13744 / PR vercel#13744 which fixed the same pattern in
@ai-sdk/openai and @ai-sdk/openai-compatible.

When an assistant message contains only tool-call parts (no text), these
four providers were sending content: "" — an empty string. Providers
backed by Amazon Bedrock reject this with:
  ValidationException: messages: text content blocks must be non-empty

Change: content: toolCalls.length > 0 ? text || null : text

This matches the OpenAI spec (content is nullable when tool_calls is
present) and what the official OpenAI SDKs send. Updated tests for all
four packages to expect null instead of "" for tool-only assistant turns.

Fixes vercel#14612

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mmartinrusso added a commit to Mmartinrusso/ai that referenced this pull request May 5, 2026
…sistant messages

Follow-up to vercel#13744 / PR vercel#13744 which fixed the same pattern in
@ai-sdk/openai and @ai-sdk/openai-compatible.

When an assistant message contains only tool-call parts (no text), these
four providers were sending content: "" — an empty string. Providers
backed by Amazon Bedrock reject this with:
  ValidationException: messages: text content blocks must be non-empty

Change: content: toolCalls.length > 0 ? text || null : text

This matches the OpenAI spec (content is nullable when tool_calls is
present) and what the official OpenAI SDKs send. Updated tests for all
four packages to expect null instead of "" for tool-only assistant turns.

Fixes vercel#14612

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
gr2m pushed a commit that referenced this pull request Jun 5, 2026
…tant messages (#13744)

## background

when an assistant message contains only tool-call parts (no text),
`convertToOpenAICompatibleChatMessages` and
`convertToOpenAIChatMessages` send `content: ""`. providers backed by
AWS Bedrock reject this with `ValidationException: messages: text
content blocks must be non-empty`

## summary

- change `content: text` to `content: text || null` for assistant
messages in both `@ai-sdk/openai-compatible` and `@ai-sdk/openai`
- update tests to expect `null` instead of `""` for tool-only assistant
messages

## checklist

- [x] tests have been added / updated (for bug fixes / features)
- [ ] documentation has been added / updated (for bug fixes / features)
- [x] a _patch_ changeset for relevant packages has been added (run
`pnpm changeset` in root)
- [x] i have reviewed this pull request (self-review)

## Future work

The same `content: text` pattern exists in `@ai-sdk/xai`,
`@ai-sdk/deepseek`, `@ai-sdk/groq`, and `@ai-sdk/mistral` and will hit
the same Bedrock error under equivalent routing. Tracked separately in
#14612.

## related issues

fixes #13466
gr2m pushed a commit that referenced this pull request Jun 5, 2026
## Background

CI was breaking ( a test wasn't updated for some reason ) after this PR
#13744

## Summary

updated snapshot
gr2m pushed a commit that referenced this pull request Jun 5, 2026
…messages with tool calls (#14950)

## background

#13744 changed `content: text` to `content: text || null` for assistant
messages. this correctly fixed tool-only messages (openai requires
`content: null` when `tool_calls` is present), but also broke the case
where an assistant message has empty text and no tool calls - openai
rejects `content: null` when `tool_calls` is absent with "Invalid value
for 'content': expected a string, got null"

per the [openai api
spec](https://developers.openai.com/api/reference/go/resources/chat/subresources/completions),
content is "required unless `tool_calls` or `function_call` is
specified"

## summary

- only send `null` when `toolCalls.length > 0`, otherwise preserve the
text string
- add regression tests for both `@ai-sdk/openai` and
`@ai-sdk/openai-compatible`

## verification

verified against live openai chat completions api with
`openai.chat('gpt-4o-mini')` - empty assistant content now sends
`content: ""` and returns a valid response

## related issues

follow-up to #13744
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 Issues related to the @ai-sdk/openai provider 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.

Bug: @ai-sdk/openai-compatible sends content:"" for assistant messages with only tool calls, causing Bedrock ValidationException

3 participants