Skip to content

fix: sanitize UIMessages before sending to LLM to prevent empty content errors - #404

Merged
lixun910 merged 1 commit into
mainfrom
xli-fix-empty-user-uimsg
Feb 28, 2026
Merged

lixun910 merged 1 commit into
mainfrom
xli-fix-empty-user-uimsg

Conversation

@lixun910

@lixun910 lixun910 commented Feb 28, 2026 •

Copy link
Copy Markdown
Collaborator
556042702-66528610-37da-4c52-974e-da54974ac53a

Problem

When conversations are interrupted mid-stream (e.g., user cancels a request), UIMessages can end up with empty text parts. When these messages are later sent to LLM APIs (particularly Bedrock), it causes errors like "text field in ContentBlock is blank".

Summary

  • Add sanitizeMessagesForLLM utility function to handle issues that occur when conversations are interrupted mid-stream
  • Filter out empty text parts (prevents Bedrock error: "text field in ContentBlock is blank")
  • Filter out empty reasoning parts
  • Add placeholder for assistant messages that have no content after cleanup to maintain conversation structure

Summary by CodeRabbit

  • Bug Fixes
    • Improved chat message processing by filtering empty content before sending to language models, ensuring cleaner data transmission.
    • Enhanced assistant message reliability by guaranteeing valid content is preserved during conversation handling.

…nt errors

Add sanitizeMessagesForLLM utility to handle issues that occur when conversations
are interrupted mid-stream:
- Filter out empty text parts (prevents Bedrock error: "text field in ContentBlock is blank")
- Filter out empty reasoning parts
- Add placeholder for assistant messages that have no content after cleanup
- Maintain conversation structure integrity

Made-with: Cursor
@coderabbitai

coderabbitai Bot commented Feb 28, 2026 •

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Two new files modify message handling in the AI chat pipeline. A new sanitizeMessagesForLLM utility function filters empty text and reasoning parts from messages and inserts a placeholder when assistant messages become empty. This function is integrated into the chat transport layer to preprocess messages before sending them to the language model.

Changes

Cohort / File(s) Summary
Message Sanitization Utility
packages/ai-core/src/utils.ts
New public function sanitizeMessagesForLLM removes empty text and reasoning parts from UIMessage arrays, preserves non-text parts, and injects "[Response interrupted]" placeholder for assistant messages that become empty after filtering.
Chat Transport Integration
packages/ai-core/src/chatTransport.ts
Imports and applies sanitizeMessagesForLLM to preprocess messages before model conversion in two code paths: local chat pipeline and tool execution handler.

Sequence Diagram(s)

sequenceDiagram
    participant ChatTransport as Chat Transport
    participant Sanitizer as sanitizeMessagesForLLM
    participant ModelConverter as convertToModelMessages
    participant LLM as Language Model

    ChatTransport->>Sanitizer: messages (with potential empty parts)
    activate Sanitizer
    Sanitizer->>Sanitizer: Filter empty text & reasoning parts
    Sanitizer->>Sanitizer: Insert placeholder if assistant message empty
    Sanitizer-->>ChatTransport: sanitized messages
    deactivate Sanitizer
    ChatTransport->>ModelConverter: sanitized messages
    activate ModelConverter
    ModelConverter-->>ChatTransport: model-compatible format
    deactivate ModelConverter
    ChatTransport->>LLM: formatted messages
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Hop, filter, clean!
Empty parts must leave the scene,
Assistant messages stay pristine,
With placeholders in between,
Sanitized and squeaky clean! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding message sanitization before sending to LLM to prevent empty content errors.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Docstrings were successfully generated.
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch xli-fix-empty-user-uimsg

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lixun910
lixun910 requested a review from ilyabo February 28, 2026 03:39

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/ai-core/src/utils.ts`:
- Around line 265-267: The current logic returns assistant messages that have
missing or empty parts and later the messages.filter at the block handling lines
around the second check (the filter at ~296-299) drops them, losing the
assistant-turn; change the handling so that when you encounter message.role ===
'assistant' and (!message.parts || message.parts.length === 0) you do not simply
return the raw message but normalize it to include an explicit empty/placeholder
part (e.g., an "interruption" or empty text part) so the assistant-turn is
preserved, and update the later filter condition (the messages.filter(...) at
~296-299) to only remove truly null/undefined entries rather than any message
with empty parts so that assistant messages with the placeholder remain in the
array; reference symbols: message, message.parts, message.role, and the
messages.filter(...) call.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c211b00 and 6be8e96.

📒 Files selected for processing (2)
  • packages/ai-core/src/chatTransport.ts
  • packages/ai-core/src/utils.ts

Comment thread packages/ai-core/src/utils.ts
@coderabbitai

coderabbitai Bot commented Feb 28, 2026 •

Copy link
Copy Markdown
Contributor

Note

Docstrings generation - SUCCESS
Generated docstrings for this pull request at #405

coderabbitai Bot added a commit that referenced this pull request Feb 28, 2026
Docstrings generation was requested by @lixun910.

* #404 (comment)

The following files were modified:

* `packages/ai-core/src/chatTransport.ts`
* `packages/ai-core/src/utils.ts`
@lixun910
lixun910 merged commit 635fbbb into main Feb 28, 2026
5 checks passed
@lixun910
lixun910 deleted the xli-fix-empty-user-uimsg branch February 28, 2026 18:47
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.

2 participants