Skip to content

fix(provider): drop whitespace-only text blocks for Anthropic/Bedrock#31376

Open
Tushar49 wants to merge 1 commit into
anomalyco:devfrom
Tushar49:fix/copilot-anthropic-whitespace-text-400
Open

fix(provider): drop whitespace-only text blocks for Anthropic/Bedrock#31376
Tushar49 wants to merge 1 commit into
anomalyco:devfrom
Tushar49:fix/copilot-anthropic-whitespace-text-400

Conversation

@Tushar49
Copy link
Copy Markdown

@Tushar49 Tushar49 commented Jun 8, 2026

Issue for this PR

Closes #31259

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Copilot's Claude models go through the Anthropic /v1/messages API, which 400s on any text block that is empty or only whitespace. ProviderTransform.message already drops empty text parts for Anthropic, but it checks part.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.toModelMessages inserts 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; oxlint clean on the 2 changed files.

Screenshots / recordings

n/a — no UI change.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

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>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 8, 2026

The following comment was made by an LLM, it may be inaccurate:

The search results show PR #31045 (fix(session): skip empty text parts in assistant message replay) which is closely related but not a duplicate. The PR description explicitly notes this distinction:

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.

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

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.

github-copilot (Claude): 400 "text content blocks must contain non-whitespace text" from whitespace-only assistant message

1 participant