Skip to content

bug: prevent crash on empty system message content array in Anthropic-family transforms - #1742

Open
ErenAta16 wants to merge 2 commits into
Portkey-AI:mainfrom
ErenAta16:bugfix/anthropic-empty-system-content
Open

bug: prevent crash on empty system message content array in Anthropic-family transforms#1742
ErenAta16 wants to merge 2 commits into
Portkey-AI:mainfrom
ErenAta16:bugfix/anthropic-empty-system-content

Conversation

@ErenAta16

@ErenAta16 ErenAta16 commented Jul 20, 2026

Copy link
Copy Markdown

Description: (required)

Two Anthropic-family system-message transforms decide whether a system/developer message is array-form by reading msg.content[0].text without first checking the array is non-empty:

if (
  SYSTEM_MESSAGE_ROLES.includes(msg.role) &&
  msg.content &&
  typeof msg.content === 'object' &&
  msg.content[0].text   // indexes [0] with no length check
) { ... }

When a request sends a system or developer message whose content is an empty array (content: []), msg.content[0] is undefined and the access throws:

TypeError: Cannot read properties of undefined (reading 'text')

content is client-controlled, so a malformed-but-plausible request becomes a 500 instead of being handled. The sibling non-system branches already guard array access with msg.content.length, so these two paths are the outliers.

  • src/providers/anthropic/chatComplete.ts: AnthropicChatCompleteConfig system transform. This config is also spread into VertexAnthropicChatCompleteConfig and used by azure-ai-inference, so the crash reaches Claude on Vertex and Azure AI Inference too.
  • src/providers/bedrock/uploadFileUtils.ts: the BedrockUploadFileTransformerConfig.anthropic system transform, used when building Bedrock batch-inference files for Claude.

Both are changed from msg.content[0].text to msg.content[0]?.text, so an empty content array is treated as no system content instead of throwing. Non-empty array content is unaffected.

Tests Run/Test cases added: (required)

  • src/providers/anthropic/chatComplete.test.ts: empty system content array no longer throws (returns []), and array-form system content still transforms as before.
  • src/providers/bedrock/uploadFileUtils.test.ts: same two cases exercised through the exported BedrockUploadFileTransformerConfig.
  • Both "empty array" cases fail on main with the TypeError above and pass with this change; the array-form cases pass before and after.

Type of Change:

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes)

The Anthropic chatComplete system-message transform read
`msg.content[0].text` to detect array-form content without first checking
the array was non-empty. A request with a system or developer message whose
content is an empty array (`content: []`) therefore threw
`TypeError: Cannot read properties of undefined (reading 'text')` instead of
being handled, surfacing as a 500 from client-controlled input. The same
config is reused by the Vertex Anthropic and Azure AI Inference providers.

Use optional chaining so an empty content array is treated as no system
content, matching how the sibling messages transform already guards with a
length check. Adds a regression test.
…ansform

Same defect as the Anthropic chatComplete transform, in the Bedrock
Anthropic upload-file config (`BedrockUploadFileTransformerConfig.anthropic`):
the system-message transform read `msg.content[0].text` without a length
check, so a system/developer message with an empty content array
(`content: []`) threw `TypeError: Cannot read properties of undefined
(reading 'text')` while building a Bedrock batch-inference file.

Use optional chaining so an empty content array yields an empty system
string. Adds a regression test that exercises the transform through the
exported `BedrockUploadFileTransformerConfig`.
@ErenAta16 ErenAta16 changed the title bug: prevent crash on empty system message content array in Anthropic transform bug: prevent crash on empty system message content array in Anthropic-family transforms Jul 20, 2026

@eeshsaxena eeshsaxena left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The optional chaining here is right, content: [] was definitely throwing before this.

One thing I ran into while looking at it: msg.content[0]?.text is doing double duty. It guards against the empty array, but it's also the only thing deciding whether this is array-form system content at all. So a system message whose first block isn't text still falls through both branches and disappears without any error.

I checked against the current main (the behaviour is the same with your ?. applied, since content[0] exists in these cases and just has no text):

content: [{type:'image', source:{...}}, {type:'text', text:'be concise'}]  ->  []
content: [{type:'text', text:''},       {type:'text', text:'be concise'}]  ->  []
content: [{type:'text', text:'be concise'}]                                ->  [{text:'be concise', type:'text'}]

The first case is the one that worries me. Anthropic accepts image blocks in system content, and a leading empty text block shows up in the wild too when something upstream builds the array programmatically. In both, "be concise" is silently dropped rather than sent, and there's no error to tell you it happened. The else if only catches string content, so nothing picks it up.

Would it be worth widening the condition to something like Array.isArray(msg.content) and letting the inner loop deal with the blocks? That keeps your empty-array fix (the loop just doesn't run) and stops the silent drop at the same time. The inner forEach pushes text: _msg.text for every block regardless of type, so it'd probably want to skip or map non-text blocks rather than emit {text: undefined, type:'text'}, but that's arguably a separate cleanup.

Not blocking, the crash fix stands on its own. Mostly flagging it because the empty-array case and the image-first case look like the same underlying assumption, and it'd be a shame to fix one and leave the other.

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