Skip to content

fix: strip trailing whitespace from final assistant message for Anthropic#4430

Open
Chase-Xuu wants to merge 6 commits intocrewAIInc:mainfrom
Chase-Xuu:fix/issue-4413-trailing-whitespace
Open

fix: strip trailing whitespace from final assistant message for Anthropic#4430
Chase-Xuu wants to merge 6 commits intocrewAIInc:mainfrom
Chase-Xuu:fix/issue-4413-trailing-whitespace

Conversation

@Chase-Xuu
Copy link

@Chase-Xuu Chase-Xuu commented Feb 9, 2026

Summary

Fixes #4413

Problem

When using LLM.call with an Anthropic model, if the final assistant message ends with trailing whitespace, the call fails with a 400 BadRequestError:

BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error', 'message': 'messages: final assistant content cannot end with trailing whitespace'}, 'request_id': '...'}

Solution

Added a check in _format_messages_for_anthropic() method in the AnthropicCompletion provider to strip trailing whitespace from the final assistant message content before sending to the API.

The fix:

  • Only applies to the final assistant message (not intermediate ones)
  • Only affects string content (not list/structured content)
  • Uses rstrip() to remove all trailing whitespace characters (spaces, tabs, newlines)

Changes

  • lib/crewai/src/crewai/llms/providers/anthropic/completion.py: Added whitespace stripping logic

Testing

Added tests in lib/crewai/tests/llms/anthropic/test_anthropic.py (from related PR #4427) to verify:

  • Trailing whitespace is stripped from final assistant messages
  • Multiple whitespace characters (spaces, tabs, newlines) are handled
  • Non-final assistant messages preserve their whitespace
  • User messages are not affected

Reproduction

from crewai import LLM
import os

llm = LLM(
    model="anthropic/claude-3-haiku-20240307",
    api_key=os.getenv('ANTHROPIC_API_KEY'),
    max_tokens=50
)

messages = [
    {"role": "user", "content": "Hello. Say world"},
    {"role": "assistant", "content": "Say: "}  # trailing space triggers the error
]

result = llm.call(messages)  # Now works without error
print(result)

Note

Medium Risk
Moderate risk because it changes Anthropic message formatting by filtering/merging messages, which can subtly alter conversation history and tool-call sequencing, though the behavior is constrained and covered by new tests.

Overview
Fixes Anthropic API 400s by hardening _format_messages_for_anthropic() to drop empty/whitespace-only messages (except an allowed empty final assistant message) and then merge consecutive same-role messages to preserve required role alternation.

Also strips trailing whitespace from the final assistant message when its content is a string, and adds unit tests covering empty-message filtering, role-merge behavior, and whitespace stripping/preservation cases.

Written by Cursor Bugbot for commit 492ec2c. This will update automatically on new commits. Configure here.

@Chase-Xuu Chase-Xuu force-pushed the fix/issue-4413-trailing-whitespace branch from 904b5cd to c6e50f3 Compare February 9, 2026 23:34
@Chase-Xuu
Copy link
Author

The Cursor Bugbot concerns have been addressed in the latest commits:

  1. Role alternation fix conflicts with test expectations: Fixed in commit c6e50f3d - updated test expectations to account for the role alternation placeholder messages.

  2. Filtering empty messages breaks alternation: Fixed in commit 9f40c3fc - the code now maintains proper user/assistant alternation by inserting minimal placeholder messages when consecutive same-role messages would result.

The test suite passes with the updated expectations.

Fixes crewAIInc#4427

The Anthropic API requires all messages to have non-empty content except
for the optional final assistant message. When messages with empty string
content are passed to the API, it returns a 400 error:

  'messages.0: all messages must have non-empty content except for the
   optional final assistant message'

This commit adds validation in _format_messages_for_anthropic() to:
- Filter out messages with empty or whitespace-only content
- Allow empty content only for the final assistant message (per API spec)
- Fall back to a default 'Hello' message if all messages are filtered out

Also adds regression tests to verify the fix.
…opic

Fixes crewAIInc#4413

Anthropic API rejects requests where the final assistant message ends
with trailing whitespace with error: 'final assistant content cannot
end with trailing whitespace'.

This fix adds a check in _format_messages_for_anthropic() to strip
trailing whitespace from the final assistant message content before
sending to the API.

The fix only applies to:
- Final assistant messages (not intermediate ones)
- String content (not list/structured content)

Added tests to verify:
- Trailing whitespace is stripped from final assistant messages
- Multiple whitespace characters are handled
- Non-final assistant messages preserve whitespace
- User messages are not affected
Address review feedback: insert placeholder messages when filtering empty
messages creates consecutive same-role messages, avoiding Anthropic's
'roles must alternate' error.
The role alternation fix inserts placeholder messages when filtering creates
consecutive same-role messages. Updated test to expect 3 messages with the
placeholder assistant message.
@Chase-Xuu Chase-Xuu force-pushed the fix/issue-4413-trailing-whitespace branch from c6e50f3 to c62e4c8 Compare February 13, 2026 16:02
…olders

Address code review feedback: inserting synthetic {'content': '...'} messages
alters the conversation meaning. Instead, merge consecutive same-role messages
to preserve all original content while maintaining Anthropic's role alternation
requirement.

Handles both string and list content formats (Anthropic supports both).
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Remove .strip() from merged message content to avoid stripping
meaningful leading/trailing whitespace from user or non-final
assistant messages during role alternation fixing.
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.

[BUG] LLM.call fails with trailing whitespace in final assistant message for anthropic models

1 participant