Skip to content

fix(bedrock): use non-whitespace placeholder for empty content blocks - #41985

Open
JiaDe-Wu wants to merge 1 commit into
NousResearch:mainfrom
JiaDe-Wu:fix/bedrock-whitespace-placeholder
Open

fix(bedrock): use non-whitespace placeholder for empty content blocks#41985
JiaDe-Wu wants to merge 1 commit into
NousResearch:mainfrom
JiaDe-Wu:fix/bedrock-whitespace-placeholder

Conversation

@JiaDe-Wu

@JiaDe-Wu JiaDe-Wu commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Sequel to #9486. That issue fixed text content blocks must be non-empty by replacing empty strings with a single space " ". But Bedrock Converse also rejects whitespace-only blocks:

ValidationException: messages: text content blocks must contain non-whitespace text

The single-space placeholder passes the non-empty check but fails the non-whitespace check — breaking resume of assistant-first history (which triggers synthetic user-message padding) and any other empty-content path. Reported in #39829.

Fix

Replace all 6 single-space placeholders with a module-level _EMPTY_CONTENT_PLACEHOLDER = "(no content)" that satisfies both the non-empty and non-whitespace checks. Also adds a .strip() guard to text parts inside content lists (previously a whitespace-only text part would slip through).

E2E verification

Tested on EC2 (us-east-2) with us.anthropic.claude-opus-4-8:

  • Assistant-first history (the bug trigger) now resumes successfully
  • No whitespace-only blocks in any padding path

6 tests updated/added. Closes #39829.

Bedrock Converse rejects whitespace-only text blocks with
'text content blocks must contain non-whitespace text' (NousResearch#39829).
The previous fix for NousResearch#9486 replaced empty strings with a single space,
which passes the non-empty check but fails the non-whitespace check —
breaking resume of assistant-first history and any padding path.

Replace all 6 single-space placeholders with a module-level
_EMPTY_CONTENT_PLACEHOLDER = '(no content)' that satisfies both checks.
Also strip-guard text parts inside content lists.

6 tests updated/added. Closes NousResearch#39829.
@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) P3 Low — cosmetic, nice to have labels Jun 9, 2026

@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 tracing the six placeholder sites; current main still has the reported whitespace-padding defect (agent/bedrock_adapter.py:505-507, 655-659).

Problems

  • The patch does not cover the tool-result branch: agent/bedrock_adapter.py:586-591 serializes empty or whitespace-only tool output directly as nested toolResult.content[].text. That can still trigger the same Bedrock validation error while preserving a required toolUse/toolResult pair.
  • The new guard handles dict text parts, but plain string items in a content list are still appended without a .strip() check at agent/bedrock_adapter.py:511-513.

Suggested changes

  • Apply the non-whitespace contract to nested tool results as well, using a descriptive sentinel if needed to preserve the pairing invariant.
  • Add regression coverage that walks the complete Converse payload, including nested toolResult.content, plus whitespace-only string list items.

This is an automated hermes-sweeper review.

Comment thread agent/bedrock_adapter.py
if part_type == "text":
text = part.get("text", "")
blocks.append({"text": text if text else " "})
blocks.append({"text": text if text and text.strip() else _EMPTY_CONTENT_PLACEHOLDER})

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.

This covers dict type: "text" parts, but plain string members in a content list are still appended without .strip() in the preceding branch. Please filter or replace those too, and add a regression test, so every emitted Converse text block satisfies the same contract.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users labels Jul 14, 2026
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 P3 Low — cosmetic, nice to have provider/bedrock AWS Bedrock (boto3, IAM) sweeper:blast-contained Sweeper blast radius: contained — one narrow path / opt-in / few users sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

3 participants