fix(provider): drop whitespace-only text blocks for Anthropic/Bedrock#31376
Open
Tushar49 wants to merge 1 commit into
Open
fix(provider): drop whitespace-only text blocks for Anthropic/Bedrock#31376Tushar49 wants to merge 1 commit into
Tushar49 wants to merge 1 commit into
Conversation
GitHub Copilot Claude models (routed through the Anthropic /v1/messages
endpoint via @ai-sdk/anthropic) returned HTTP 400 "messages: text content
blocks must contain non-whitespace text" whenever the conversation history
contained an assistant turn whose only text block was whitespace (e.g. a
single space). This commonly happens when a cheap fallback model returns an
empty/whitespace response that is later replayed to Claude, and it makes the
affected models unusable mid-conversation even though they are listed and
selectable.
ProviderTransform.message already strips empty ("") text/reasoning parts for
Anthropic, but the text guard only matched exactly "" and let whitespace-only
blocks (" ", "\n", ...) through, while the reasoning guard right below already
used .trim(). Treat whitespace-only text the same as empty.
A single space is also deliberately emitted by MessageV2.toModelMessages as a
separator between *signed* reasoning blocks, so preserve whitespace-only text
only when the message still carries surviving signed/redacted Anthropic
reasoning (the AI SDK merges that separator into an adjacent block). Bedrock
never emits that separator, so whitespace-only text is dropped unconditionally
there.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
|
The following comment was made by an LLM, it may be inaccurate: The search results show PR #31045 (
PR #31045 operates at a different layer (session message replay) and only filters exact empty strings, while PR #31376 targets the provider transform layer and catches whitespace-only blocks (including single spaces). No duplicate PRs found |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #31259
Type of change
What does this PR do?
Copilot's Claude models go through the Anthropic
/v1/messagesAPI, which 400s on any text block that is empty or only whitespace.ProviderTransform.messagealready drops empty text parts for Anthropic, but it checkspart.text !== "", so a lone" "slips through and the whole request fails. The reasoning check right beside it already uses.trim()— I just make the text check match.The one space I keep is the separator
MessageV2.toModelMessagesinserts between signed reasoning blocks; it's only kept when the message still has signed Anthropic reasoning (the SDK merges it into a neighbouring block so it never hits the API on its own). Bedrock has the same API limits but no separator, so I trim it there unconditionally.Not a dup of #31045 — that drops empty parts earlier in message-v2 but only for exact
"". It doesn't catch a" "that's already saved in a session, which is what my logs actually hit.How did you verify your code works?
bun test packages/opencode/test/provider/transform.test.ts. Added 5 cases: the exact failing message, mixed empty + real text, the signed-reasoning separator (kept), an unsigned-reasoning case (dropped, no leak), and Bedrock. All 14 in the "anthropic empty content filtering" suite pass;oxlintclean on the 2 changed files.Screenshots / recordings
n/a — no UI change.
Checklist