Skip to content

fix(bedrock): non-whitespace placeholder for empty Converse text blocks (salvage #66167) - #67978

Merged
teknium1 merged 3 commits into
mainfrom
fix/bedrock-whitespace-text-blocks
Jul 20, 2026
Merged

fix(bedrock): non-whitespace placeholder for empty Converse text blocks (salvage #66167)#67978
teknium1 merged 3 commits into
mainfrom
fix/bedrock-whitespace-text-blocks

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Summary

Bedrock's Converse path can no longer send whitespace-only text blocks — the API rejects them ("text content blocks must contain non-whitespace text"), and main's lone-space " " placeholder was itself whitespace, so empty assistant/tool content still 400'd mid-conversation.

Salvages the fix half of #66167 (@Polyhistor — both commits cherry-picked with authorship; the PR's context-table half is superseded by the sibling context-lengths PR).

Changes

  • agent/bedrock_adapter.py: _safe_text() guard routes every content shape (None, empty, whitespace-only, non-string, list items, dict text parts) to a non-whitespace (empty) placeholder in _convert_content_to_converse
  • tests/agent/test_bedrock_empty_text_blocks.py: dedicated 115-line suite; stale lone-space assertions updated

Validation

Check Result
test_bedrock_adapter.py + test_bedrock_empty_text_blocks.py 149/149 pass
E2E: 7 content shapes through _convert_content_to_converse zero whitespace blocks emitted

Closes #66167 (context-table half superseded; this PR carries the fix half with authorship). Credit: @Polyhistor.

Infographic

bedrock-whitespace-text-blocks

Polyhistor and others added 3 commits July 20, 2026 03:04
Bedrock Converse rejects text content blocks that are empty OR
whitespace-only (ValidationException: "text content blocks must
contain non-whitespace text"). The prior fix attempt substituted a
single space (" ") for missing content -- but a lone space IS
whitespace, so it was rejected by the exact same validation rule it
was meant to satisfy. This caused a deterministic, unrecoverable
retry-loop failure once any blank/whitespace assistant, tool, or user
turn entered history (most commonly via context-compaction rewriting
a turn to a blank string).

Adds _safe_text()/_EMPTY_TEXT_PLACEHOLDER ("(empty)") and applies it
everywhere a blank text block could reach the wire: user/assistant
content conversion, tool results, the assistant-empty-turn fallback,
and the first/last-message user-alternation padding. System-prompt
blocks are the one exception: blank parts are dropped entirely rather
than placeholder-filled, since a system prompt block should never
carry meaningless placeholder text.

Adds tests/agent/test_bedrock_empty_text_blocks.py (11 tests, was
already present uncommitted -- codifies the exact failing history
from issue #9486 and asserts no blank block ever reaches Bedrock).

Verified against the actual failed request dump from this session
(27-message payload) -- replaying it through the fixed converter now
produces zero blank/whitespace-only blocks.
…text, update stale placeholder assertions

Addresses hermes-sweeper review on PR #66167:

1. _convert_content_to_converse() still emitted {"text": part} directly
   for plain-string items inside a content list (as opposed to
   {"type": "text"} dicts), bypassing _safe_text() entirely. A
   whitespace-only string item (e.g. ["   "]) could still reach Bedrock
   as a blank block. Now routed through _safe_text().

2. tests/agent/test_bedrock_adapter.py::TestEmptyTextBlockFix asserted
   the pre-fix behavior (whitespace -> literal space " "), contradicting
   the new _safe_text()/_EMPTY_TEXT_PLACEHOLDER behavior added in
   4618095. Updated assertions to expect the non-whitespace placeholder,
   plus added a regression test for the list-string-item case above.
@alt-glitch alt-glitch added type/bug Something isn't working comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint provider/bedrock AWS Bedrock (boto3, IAM) P2 Medium — degraded but workaround exists labels Jul 20, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #66167, #64858, and #60628. This maintainer salvage uses the replacement/strip approach across additional Bedrock content and tool-result paths; the open work remains a competing/consolidation cluster, not a duplicate relationship.

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/bedrock AWS Bedrock (boto3, IAM) type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants