fix(litellm): guard against Content with no parts in _content_to_message_param#6312
Open
anxkhn wants to merge 1 commit into
Open
fix(litellm): guard against Content with no parts in _content_to_message_param#6312anxkhn wants to merge 1 commit into
anxkhn wants to merge 1 commit into
Conversation
…age_param types.Content(role="user") defaults parts to None, and the fallback path can produce an empty user turn, so iterating content.parts in _content_to_message_param raised TypeError: 'NoneType' object is not iterable during LiteLLM request assembly, before any model call. Normalize parts to content.parts or [] once (matching the existing idiom in this module and the google_llm adapter, which skips contents without parts) and iterate the normalized list in all three branches. A content with no parts now yields a message with empty content instead of crashing. Add regression tests covering user and assistant roles for both parts=None and parts=[].
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
2. Or, if no issue exists, describe the change:
Problem:
LiteLlm._content_to_message_paramiteratescontent.partsdirectly in threeplaces. A
types.Contentcan legitimately haveparts=None, so those iterations raiseTypeError: 'NoneType' object is not iterableduring LiteLLM request assembly,before any model call.
types.Content(role="user")defaultspartstoNone, and an empty user turn canreach the adapter through the request contents. Minimal reproduction:
The native Gemini adapter already tolerates this case:
google_llm.pyskips acontent with no parts (
if not content.parts: continue). The LiteLLM adapter doesnot, so the two paths behave inconsistently for the same input.
Solution:
Normalize
partsonce at the top of_content_to_message_param(
parts = content.parts or []) and iterate the normalized list in all threebranches (the function-response iteration, the user-branch comprehension, and the
assistant-branch iteration). This mirrors the
content.parts or []idiom already usedin this same module and keeps the LiteLLM adapter consistent with the Gemini
adapter. A content with no parts now yields a message with empty content instead of
crashing.
The change is limited to the normalization; no other behavior is altered. Normal
text content, mixed tool + text content, and multipart function responses are
unaffected.
Testing Plan
Unit Tests:
Added parametrized regression tests in
tests/unittests/models/test_litellm.pycovering bothparts=Noneandparts=[]for the user and assistant roles, asserting the role is preserved andcontentisNone(no exception raised):test_content_to_message_param_user_message_without_partstest_content_to_message_param_assistant_message_without_partsThese fail on
mainat the firstfor part in content.partsiteration with thereported
TypeErrorand pass with this change.pytestsummary for the affected module:Broader model suite (no regressions):
Manual End-to-End (E2E) Tests:
Direct reproduction via the adapter entry point (see the snippet under
"Problem"): before the change,
_content_to_message_param(types.Content(role="user"))raises
TypeError: 'NoneType' object is not iterable; after the change it returns{'role': 'user', 'content': None}. The same holds forrole="assistant"and forparts=[].Checklist
Additional context
The guard makes the LiteLLM adapter consistent with the Gemini adapter
(
google_llm.py), which already tolerates a content without parts.The diff (for reference; already committed on the branch)
src/google/adk/models/lite_llm.py(+9/-3),tests/unittests/models/test_litellm.py(+20). Net +29/-3.parts = content.parts or []right after_ensure_litellm_imported().for part in content.parts/[... for part in content.parts ...]sites (function-response iteration, user comprehension, assistant iteration) with the
normalized
parts.Noneand[]).