Skip to content

Commit 28d36b5

Browse files
committed
fix(ai): Handle Pydantic model classes in _normalize_data
Previously, _normalize_data would attempt to call model_dump() on Pydantic model classes (types) when they were passed as arguments, which would fail. This commonly occurs when model classes are used in schema definitions. This change adds an inspect.isclass() check to detect when a class type is passed instead of an instance. For classes, we now return a string representation "<ClassType: ClassName>" instead of attempting to call model_dump().
1 parent 3c32bb4 commit 28d36b5

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

sentry_sdk/ai/utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import inspect
12
import json
23
from collections import deque
34
from typing import TYPE_CHECKING
@@ -38,6 +39,11 @@ def _normalize_data(data, unpack=True):
3839
# type: (Any, bool) -> Any
3940
# convert pydantic data (e.g. OpenAI v1+) to json compatible format
4041
if hasattr(data, "model_dump"):
42+
# Check if it's a class (type) rather than an instance
43+
# Model classes can be passed as arguments (e.g., for schema definitions)
44+
if inspect.isclass(data):
45+
return f"<ClassType: {data.__name__}>"
46+
4147
try:
4248
return _normalize_data(data.model_dump(), unpack=unpack)
4349
except Exception as e:

tests/utils/test_general.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33

44
import pytest
5+
from sentry_sdk.ai.utils import _normalize_data
56

67

78
from sentry_sdk.utils import (
@@ -621,3 +622,28 @@ def test_failed_base64_conversion(input):
621622
)
622623
def test_strip_string(input, max_length, result):
623624
assert strip_string(input, max_length) == result
625+
626+
627+
def test_normalize_data_with_pydantic_class():
628+
"""Test that _normalize_data handles Pydantic model classes"""
629+
class TestClass:
630+
name: str = None
631+
632+
def __init__(self, name: str):
633+
self.name = name
634+
635+
def model_dump(self):
636+
return {"name": self.name}
637+
638+
# Test with class (should NOT call model_dump())
639+
result = _normalize_data(TestClass)
640+
assert result == "<ClassType: TestClass>"
641+
642+
# Test with instance (should call model_dump())
643+
instance = TestClass(name="test")
644+
result = _normalize_data(instance)
645+
assert result == {"name": "test"}
646+
647+
# Test with dict containing class
648+
result = _normalize_data({"schema": TestClass, "count": 5})
649+
assert result == {"schema": "<ClassType: TestClass>", "count": 5}

0 commit comments

Comments
 (0)