fix(agent): guard against None url in Bedrock image_url conversion - #55699
fix(agent): guard against None url in Bedrock image_url conversion#55699AlexFucuson9 wants to merge 2 commits into
Conversation
When an image_url part has 'url': null (None), .get('url', '') returns
None (not ''), causing url.startswith('data:') to crash with
AttributeError: 'NoneType' object has no attribute 'startswith'.
Fix: use (x.get('url') or '') which coalesces None to ''.
Fixes NousResearch#55686
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused Bedrock null-handling fix. The current-main premise is valid: agent/bedrock_adapter.py:522-523 can pass a present None URL to startswith.
Problems
agent/bedrock_adapter.py:522coalesces only falsey values. A truthy non-string URL such as123still reachesurl.startswith(...)at line 523 and raisesAttributeError. Linked issue #55686 explicitly covers non-string URLs.- No regression tests are included. Existing image conversion coverage at
tests/agent/test_bedrock_adapter.py:332-348covers a valid data URL only. - The additional lifecycle hunk at
agent/bedrock_adapter.py:1148still fails ifmodelLifecycleitself isNone, becauselifecycle.get(...)is invoked before any container normalization.
Suggested changes
- Type-check the resolved image URL before calling
startswith, and add null and truthy non-string regression cases. - If retaining the lifecycle guard, normalize
modelLifecycleitself and cover that shape with a model-discovery test.
Automated hermes-sweeper review.
| elif part_type == "image_url": | ||
| image_url = part.get("image_url", {}) | ||
| url = image_url.get("url", "") if isinstance(image_url, dict) else "" | ||
| url = (image_url.get("url") or "") if isinstance(image_url, dict) else "" |
There was a problem hiding this comment.
This coalesces None, but truthy non-string values remain unchanged: {"url": 123} still reaches url.startswith(...) below and raises AttributeError. #55686 explicitly includes non-string URLs; normalize by type before the prefix check and add that regression case.
| # Only include active, streaming-capable, text-output models | ||
| lifecycle = summary.get("modelLifecycle", {}) | ||
| if lifecycle.get("status", "").upper() != "ACTIVE": | ||
| if (lifecycle.get("status") or "").upper() != "ACTIVE": |
There was a problem hiding this comment.
This protects a null status, but not a present modelLifecycle=None: the assignment above leaves lifecycle as None and .get(...) still raises. If this extra hardening remains, normalize the containing lifecycle value as well and add a regression test.
Summary
Guard against
Noneurl in Bedrock Converse image_url conversion.Problem (P2 #55686)
When an image_url part has
"url": null(PythonNone),image_url.get("url", "")returnsNone(not""), because.get()only uses the default when the key is absent, not when the value isNone. This causesurl.startswith("data:")to crash withAttributeError: 'NoneType' object has no attribute 'startswith'.Fix
Use
(image_url.get("url") or "")which coalescesNoneto"".Changes
agent/bedrock_adapter.py: 1 line changedFixes #55686