Skip to content

Commit cde852a

Browse files
cursoragentclaude
andcommitted
Fix AttributeError when image_url is string shorthand with base64 data
Handle both string shorthand and dict formats for image_url in _is_image_type_with_blob_content and redact_blob_message_parts functions. The OpenAI API supports both formats: - {"type": "image_url", "image_url": "data:..."} - {"type": "image_url", "image_url": {"url": "data:..."}} Previously, calling .get("url", "") on a string raised AttributeError. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 51ff087 commit cde852a

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

sentry_sdk/ai/utils.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,14 @@ def _is_image_type_with_blob_content(item: "Dict[str, Any]") -> bool:
597597
if item.get("type") != "image_url":
598598
return False
599599

600-
image_url = item.get("image_url", {}).get("url", "")
600+
image_url_data = item.get("image_url")
601+
if isinstance(image_url_data, str):
602+
image_url = image_url_data
603+
elif isinstance(image_url_data, dict):
604+
image_url = image_url_data.get("url", "")
605+
else:
606+
return False
607+
601608
data_url_match = DATA_URL_BASE64_REGEX.match(image_url)
602609

603610
return bool(data_url_match)
@@ -682,7 +689,11 @@ def redact_blob_message_parts(
682689
if item.get("type") == "blob":
683690
item["content"] = BLOB_DATA_SUBSTITUTE
684691
elif _is_image_type_with_blob_content(item):
685-
item["image_url"]["url"] = BLOB_DATA_SUBSTITUTE
692+
image_url_data = item.get("image_url")
693+
if isinstance(image_url_data, str):
694+
item["image_url"] = BLOB_DATA_SUBSTITUTE
695+
elif isinstance(image_url_data, dict):
696+
item["image_url"]["url"] = BLOB_DATA_SUBSTITUTE
686697

687698
return messages_copy
688699

tests/test_ai_monitoring.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,38 @@ def test_redacts_single_blob_within_image_url_content(self):
845845
assert result[0]["content"][1]["type"] == "image_url"
846846
assert result[0]["content"][1]["image_url"]["url"] == BLOB_DATA_SUBSTITUTE
847847

848+
def test_redacts_image_url_string_shorthand_with_blob(self):
849+
"""Test redacting image_url using string shorthand format with base64 data"""
850+
messages = [
851+
{
852+
"role": "user",
853+
"content": [
854+
{
855+
"text": "How many ponies do you see in the image?",
856+
"type": "text",
857+
},
858+
{
859+
"type": "image_url",
860+
"image_url": "data:image/jpeg;base64,/9j/4AAQSkZJRg==",
861+
},
862+
],
863+
}
864+
]
865+
866+
original_blob_content = messages[0]["content"][1]
867+
868+
result = redact_blob_message_parts(messages)
869+
870+
assert messages[0]["content"][1] == original_blob_content
871+
872+
assert (
873+
result[0]["content"][0]["text"]
874+
== "How many ponies do you see in the image?"
875+
)
876+
assert result[0]["content"][0]["type"] == "text"
877+
assert result[0]["content"][1]["type"] == "image_url"
878+
assert result[0]["content"][1]["image_url"] == BLOB_DATA_SUBSTITUTE
879+
848880
def test_does_not_redact_image_url_content_with_non_blobs(self):
849881
messages = [
850882
{

0 commit comments

Comments
 (0)