fix: trim trailing whitespaces for anthropic and bedrock anthropic provider - #3496
Conversation
📝 WalkthroughWalkthroughTrim trailing right-side whitespace (spaces, newlines, tabs, carriage returns) from the last assistant message's text ContentBlock in Anthropic and Bedrock request/conversion paths across four provider modules. ChangesTrailing Whitespace Normalization for Assistant Messages
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
This stack of pull requests is managed by Graphite. Learn more about stacking. |
4ae07e7 to
d463298
Compare
Confidence Score: 5/5Safe to merge — the change is narrowly scoped to outbound request formatting and cannot affect response handling or other providers. All four modified sites use a backward-iterating loop with an early No files require special attention. Important Files Changed
Reviews (3): Last reviewed commit: "fix: trim trailing whitespaces for anthr..." | Re-trigger Greptile |
c531a7e to
d3d95a6
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@core/providers/bedrock/chat.go`:
- Around line 46-57: The final assistant message trimming only trims the first
text block found from the end (the loop breaks), leaving earlier blocks with
trailing whitespace; in the Anthropic-only branch (check using
schemas.IsAnthropicModel and BedrockMessageRoleAssistant) iterate over all
entries in bedrockReq.Messages[lastMsgIndex].Content and for each block with a
non-nil Text field set bedrockReq.Messages[lastMsgIndex].Content[i].Text to
schemas.Ptr(strings.TrimRight(*blocks[i].Text, " \n\r\t")) instead of breaking
after the first trim so every text block in that final assistant message is
trimmed.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7b4705a7-6f1b-4972-a841-9a2a4b8e3f8d
📒 Files selected for processing (4)
core/providers/anthropic/chat.gocore/providers/anthropic/responses.gocore/providers/bedrock/chat.gocore/providers/bedrock/responses.go
🚧 Files skipped from review as they are similar to previous changes (3)
- core/providers/anthropic/chat.go
- core/providers/anthropic/responses.go
- core/providers/bedrock/responses.go
d3d95a6 to
df07242
Compare
Merge activity
|
…ovider (#3496) ## Summary Trailing whitespace (spaces, newlines, carriage returns, tabs) in the last assistant message is stripped before sending requests to Anthropic and Bedrock (Anthropic models). This prevents API errors that can occur when assistant prefill messages end with whitespace, which Anthropic's API rejects. ## Changes - For the Anthropic provider, all text content blocks in the final assistant message are right-trimmed of whitespace before the request is sent, applied in both `chat.go` and `responses.go`. - For the Bedrock provider, the same trimming is applied to text blocks in the final assistant message, but only when the target model is an Anthropic model (since prefill is an Anthropic-specific concept), applied in both `chat.go` and `responses.go`. ## Type of change - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test Send a chat completion request where the last message has `role: assistant` and its content ends with trailing whitespace or newlines. ### chat completions ``` curl --location 'http://localhost:8080/v1/chat/completions' \ --header 'Content-Type: application/json' \ --data '{ // "model": "anthropic/claude-haiku-4-5-20251001", // "model": "anthropic/claude-opus-4-1-20250805", // "model": "anthropic/claude-opus-4-20250514", // "model": "anthropic/claude-opus-4-5-20251101", // "model": "anthropic/claude-opus-4-6", // "model": "anthropic/claude-opus-4-7", // "model": "anthropic/claude-sonnet-4-20250514", // "model": "anthropic/claude-sonnet-4-5-20250929", // "model": "anthropic/claude-sonnet-4-6", // "model": "bedrock/us.anthropic.claude-3-haiku-20240307-v1:0", // "model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-1-20250805-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-6-v1", // "model": "bedrock/us.anthropic.claude-opus-4-7", // "model": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", // "model": "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0", "model": "bedrock/us.anthropic.claude-sonnet-4-6", "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": "Hello " // trailing whitespace } ] }' ``` ### anthropic integration (v1/messages) ``` curl --location 'http://localhost:8080/anthropic/v1/messages' \ --header 'Content-Type: application/json' \ --data '{ // "model": "anthropic/claude-haiku-4-5-20251001", // "model": "anthropic/claude-opus-4-1-20250805", // "model": "anthropic/claude-opus-4-20250514", // "model": "anthropic/claude-opus-4-5-20251101", // "model": "anthropic/claude-opus-4-6", // "model": "anthropic/claude-opus-4-7", // "model": "anthropic/claude-sonnet-4-20250514", // "model": "anthropic/claude-sonnet-4-5-20250929", // "model": "anthropic/claude-sonnet-4-6", // "model": "bedrock/us.anthropic.claude-3-haiku-20240307-v1:0", // "model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-1-20250805-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-6-v1", // "model": "bedrock/us.anthropic.claude-opus-4-7", // "model": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", // "model": "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0", "model": "bedrock/us.anthropic.claude-sonnet-4-6", "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": "Hey " ] }' ``` ``` "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": [ { "type": "text", "text": "Hey " } ] } ] ``` ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations No security implications. This change only modifies outbound message content formatting before it reaches the provider API. ## Checklist - [x] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [x] I verified the CI pipeline passes locally if applicable
…ovider (#3496) ## Summary Trailing whitespace (spaces, newlines, carriage returns, tabs) in the last assistant message is stripped before sending requests to Anthropic and Bedrock (Anthropic models). This prevents API errors that can occur when assistant prefill messages end with whitespace, which Anthropic's API rejects. ## Changes - For the Anthropic provider, all text content blocks in the final assistant message are right-trimmed of whitespace before the request is sent, applied in both `chat.go` and `responses.go`. - For the Bedrock provider, the same trimming is applied to text blocks in the final assistant message, but only when the target model is an Anthropic model (since prefill is an Anthropic-specific concept), applied in both `chat.go` and `responses.go`. ## Type of change - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test Send a chat completion request where the last message has `role: assistant` and its content ends with trailing whitespace or newlines. ### chat completions ``` curl --location 'http://localhost:8080/v1/chat/completions' \ --header 'Content-Type: application/json' \ --data '{ // "model": "anthropic/claude-haiku-4-5-20251001", // "model": "anthropic/claude-opus-4-1-20250805", // "model": "anthropic/claude-opus-4-20250514", // "model": "anthropic/claude-opus-4-5-20251101", // "model": "anthropic/claude-opus-4-6", // "model": "anthropic/claude-opus-4-7", // "model": "anthropic/claude-sonnet-4-20250514", // "model": "anthropic/claude-sonnet-4-5-20250929", // "model": "anthropic/claude-sonnet-4-6", // "model": "bedrock/us.anthropic.claude-3-haiku-20240307-v1:0", // "model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-1-20250805-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-6-v1", // "model": "bedrock/us.anthropic.claude-opus-4-7", // "model": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", // "model": "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0", "model": "bedrock/us.anthropic.claude-sonnet-4-6", "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": "Hello " // trailing whitespace } ] }' ``` ### anthropic integration (v1/messages) ``` curl --location 'http://localhost:8080/anthropic/v1/messages' \ --header 'Content-Type: application/json' \ --data '{ // "model": "anthropic/claude-haiku-4-5-20251001", // "model": "anthropic/claude-opus-4-1-20250805", // "model": "anthropic/claude-opus-4-20250514", // "model": "anthropic/claude-opus-4-5-20251101", // "model": "anthropic/claude-opus-4-6", // "model": "anthropic/claude-opus-4-7", // "model": "anthropic/claude-sonnet-4-20250514", // "model": "anthropic/claude-sonnet-4-5-20250929", // "model": "anthropic/claude-sonnet-4-6", // "model": "bedrock/us.anthropic.claude-3-haiku-20240307-v1:0", // "model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-1-20250805-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-6-v1", // "model": "bedrock/us.anthropic.claude-opus-4-7", // "model": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", // "model": "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0", "model": "bedrock/us.anthropic.claude-sonnet-4-6", "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": "Hey " ] }' ``` ``` "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": [ { "type": "text", "text": "Hey " } ] } ] ``` ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations No security implications. This change only modifies outbound message content formatting before it reaches the provider API. ## Checklist - [x] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [x] I verified the CI pipeline passes locally if applicable
…ovider (#3496) ## Summary Trailing whitespace (spaces, newlines, carriage returns, tabs) in the last assistant message is stripped before sending requests to Anthropic and Bedrock (Anthropic models). This prevents API errors that can occur when assistant prefill messages end with whitespace, which Anthropic's API rejects. ## Changes - For the Anthropic provider, all text content blocks in the final assistant message are right-trimmed of whitespace before the request is sent, applied in both `chat.go` and `responses.go`. - For the Bedrock provider, the same trimming is applied to text blocks in the final assistant message, but only when the target model is an Anthropic model (since prefill is an Anthropic-specific concept), applied in both `chat.go` and `responses.go`. ## Type of change - [x] Bug fix - [ ] Feature - [ ] Refactor - [ ] Documentation - [ ] Chore/CI ## Affected areas - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [ ] UI (React) - [ ] Docs ## How to test Send a chat completion request where the last message has `role: assistant` and its content ends with trailing whitespace or newlines. ### chat completions ``` curl --location 'http://localhost:8080/v1/chat/completions' \ --header 'Content-Type: application/json' \ --data '{ // "model": "anthropic/claude-haiku-4-5-20251001", // "model": "anthropic/claude-opus-4-1-20250805", // "model": "anthropic/claude-opus-4-20250514", // "model": "anthropic/claude-opus-4-5-20251101", // "model": "anthropic/claude-opus-4-6", // "model": "anthropic/claude-opus-4-7", // "model": "anthropic/claude-sonnet-4-20250514", // "model": "anthropic/claude-sonnet-4-5-20250929", // "model": "anthropic/claude-sonnet-4-6", // "model": "bedrock/us.anthropic.claude-3-haiku-20240307-v1:0", // "model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-1-20250805-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-6-v1", // "model": "bedrock/us.anthropic.claude-opus-4-7", // "model": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", // "model": "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0", "model": "bedrock/us.anthropic.claude-sonnet-4-6", "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": "Hello " // trailing whitespace } ] }' ``` ### anthropic integration (v1/messages) ``` curl --location 'http://localhost:8080/anthropic/v1/messages' \ --header 'Content-Type: application/json' \ --data '{ // "model": "anthropic/claude-haiku-4-5-20251001", // "model": "anthropic/claude-opus-4-1-20250805", // "model": "anthropic/claude-opus-4-20250514", // "model": "anthropic/claude-opus-4-5-20251101", // "model": "anthropic/claude-opus-4-6", // "model": "anthropic/claude-opus-4-7", // "model": "anthropic/claude-sonnet-4-20250514", // "model": "anthropic/claude-sonnet-4-5-20250929", // "model": "anthropic/claude-sonnet-4-6", // "model": "bedrock/us.anthropic.claude-3-haiku-20240307-v1:0", // "model": "bedrock/us.anthropic.claude-haiku-4-5-20251001-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-1-20250805-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-5-20251101-v1:0", // "model": "bedrock/us.anthropic.claude-opus-4-6-v1", // "model": "bedrock/us.anthropic.claude-opus-4-7", // "model": "bedrock/us.anthropic.claude-sonnet-4-20250514-v1:0", // "model": "bedrock/us.anthropic.claude-sonnet-4-5-20250929-v1:0", "model": "bedrock/us.anthropic.claude-sonnet-4-6", "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": "Hey " ] }' ``` ``` "messages": [ { "role": "user", "content": "Hello" }, { "role": "assistant", "content": [ { "type": "text", "text": "Hey " } ] } ] ``` ## Breaking changes - [ ] Yes - [x] No ## Related issues ## Security considerations No security implications. This change only modifies outbound message content formatting before it reaches the provider API. ## Checklist - [x] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [x] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [x] I verified the CI pipeline passes locally if applicable

Summary
Trailing whitespace (spaces, newlines, carriage returns, tabs) in the last assistant message is stripped before sending requests to Anthropic and Bedrock (Anthropic models). This prevents API errors that can occur when assistant prefill messages end with whitespace, which Anthropic's API rejects.
Changes
chat.goandresponses.go.chat.goandresponses.go.Type of change
Affected areas
How to test
Send a chat completion request where the last message has
role: assistantand its content ends with trailing whitespace or newlines.chat completions
anthropic integration (v1/messages)
Breaking changes
Related issues
Security considerations
No security implications. This change only modifies outbound message content formatting before it reaches the provider API.
Checklist
docs/contributing/README.mdand followed the guidelines