Skip to content

fix(anthropic): filter empty text blocks from assistant messages - #9491

Closed
ygd58 wants to merge 1 commit into
NousResearch:mainfrom
ygd58:fix/bedrock-empty-text-blocks
Closed

fix(anthropic): filter empty text blocks from assistant messages#9491
ygd58 wants to merge 1 commit into
NousResearch:mainfrom
ygd58:fix/bedrock-empty-text-blocks

Conversation

@ygd58

@ygd58 ygd58 commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Problem

Closes #9486

Bedrock and strict Anthropic-compatible endpoints reject messages where a text content block has an empty text field:

ValidationException: messages: text content blocks must be non-empty

This happens in multi-turn conversations when an assistant message contains an empty text block alongside tool_use blocks.

Root Cause

In convert_to_anthropic_messages(), user messages already had an empty-block guard. Assistant messages were missing it — converted_content blocks were extended into the final list without filtering empty text entries.

Fix

Skip text blocks with empty/whitespace text when building the assistant content block list:

for blk in converted_content:
    if (
        isinstance(blk, dict)
        and blk.get("type") == "text"
        and not blk.get("text", "").strip()
    ):
        continue  # drop empty text block
    blocks.append(blk)

Before / After

Before: Multi-turn chat with tool calls → empty text block in assistant message → Bedrock 400 error

After: Empty text blocks silently dropped → valid message sent → no error

Bedrock and strict Anthropic-compatible endpoints reject messages where
a text content block has an empty or whitespace-only 'text' field with:

  ValidationException: messages: text content blocks must be non-empty

This happens in multi-turn conversations when context compression or
streaming produces an assistant message with an empty text block
alongside tool_use blocks.

User messages already had this guard (falls back to '(empty message)').
Assistant messages were missing it — converted_content blocks were
extended into the final list without filtering empty text entries.

Fix: skip text blocks with empty/whitespace 'text' when building the
assistant content block list in convert_to_anthropic_messages().

Fixes NousResearch#9486
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/anthropic Anthropic native Messages API provider/bedrock AWS Bedrock (boto3, IAM) labels Apr 27, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Related to #11929 — both sanitize empty text content blocks in assistant messages. #11929 patches run_agent.py while this one patches convert_to_anthropic_messages(). May overlap.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for isolating the assistant-list conversion path. The underlying normal-path defect remains on current main: agent/anthropic_adapter.py:1981-1985 converts and extends assistant content-list blocks without filtering blank text, while _convert_content_part_to_anthropic() preserves the original text at agent/anthropic_adapter.py:1733-1739.

Problems

  • No regression test accompanies the change. tests/agent/test_anthropic_adapter.py:1257-1277 covers content="", which bypasses the list conversion branch; add a list-content case with empty and whitespace-only text alongside tool_calls.
  • Current main also has an ordered-replay fast path at agent/anthropic_adapter.py:1937-1978. It returns blocks before the normal conversion loop, and _sanitize_replay_block() preserves text values at agent/anthropic_adapter.py:1873-1882; a salvage should enforce the same non-empty-text invariant there while retaining signed-block order.

Suggested changes

  • Reapply the filter in current _convert_assistant_message() rather than the pre-refactor location from this branch.
  • Add normal and ordered-replay regression tests asserting emitted Anthropic text blocks are non-blank.

Automated hermes-sweeper review.

and not blk.get("text", "").strip()
):
continue # drop empty text block
blocks.append(blk)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Please add a regression test for an assistant content list containing empty and whitespace-only text blocks plus tool_calls; the existing empty-string assistant case does not enter this branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint P2 Medium — degraded but workaround exists provider/anthropic Anthropic native Messages API provider/bedrock AWS Bedrock (boto3, IAM) sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Bedrock API 400 Error: "text content blocks must be non-empty" when using custom provider

4 participants