Skip to content

Commit 7cd8ec3

Browse files
mike-luabaseclaude
andcommitted
fix: prevent Anthropic API errors from empty message content
- Check for empty text content before adding to assistant messages - Only append messages with non-empty content to avoid API errors - Filter empty strings in user prompts before yielding text blocks This fixes the invalid_request_error: "all messages must have non-empty content except for the optional final assistant message" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent ea837b9 commit 7cd8ec3

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

pydantic_ai_slim/pydantic_ai/models/anthropic.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,8 @@ async def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[Be
322322
assistant_content_params: list[BetaTextBlockParam | BetaToolUseBlockParam] = []
323323
for response_part in m.parts:
324324
if isinstance(response_part, TextPart):
325-
assistant_content_params.append(BetaTextBlockParam(text=response_part.content, type='text'))
325+
if response_part.content: # Only add non-empty text
326+
assistant_content_params.append(BetaTextBlockParam(text=response_part.content, type='text'))
326327
else:
327328
tool_use_block_param = BetaToolUseBlockParam(
328329
id=_guard_tool_call_id(t=response_part),
@@ -331,7 +332,8 @@ async def _map_message(self, messages: list[ModelMessage]) -> tuple[str, list[Be
331332
input=response_part.args_as_dict(),
332333
)
333334
assistant_content_params.append(tool_use_block_param)
334-
anthropic_messages.append(BetaMessageParam(role='assistant', content=assistant_content_params))
335+
if len(assistant_content_params) > 0:
336+
anthropic_messages.append(BetaMessageParam(role='assistant', content=assistant_content_params))
335337
else:
336338
assert_never(m)
337339
system_prompt = '\n\n'.join(system_prompt_parts)
@@ -344,11 +346,13 @@ async def _map_user_prompt(
344346
part: UserPromptPart,
345347
) -> AsyncGenerator[BetaContentBlockParam]:
346348
if isinstance(part.content, str):
347-
yield BetaTextBlockParam(text=part.content, type='text')
349+
if part.content: # Only yield non-empty text
350+
yield BetaTextBlockParam(text=part.content, type='text')
348351
else:
349352
for item in part.content:
350353
if isinstance(item, str):
351-
yield BetaTextBlockParam(text=item, type='text')
354+
if item: # Only yield non-empty text
355+
yield BetaTextBlockParam(text=item, type='text')
352356
elif isinstance(item, BinaryContent):
353357
if item.is_image:
354358
yield BetaImageBlockParam(

0 commit comments

Comments
 (0)