From c95d0f19b44c16bd21308a4177d4204510c4fffb Mon Sep 17 00:00:00 2001 From: Muhtasim-Munif-Fahim Date: Mon, 8 Jun 2026 06:32:27 +0600 Subject: [PATCH 1/4] fix: parse realtime error messages --- .../beta/realtime/realtime_response_status.py | 3 ++ .../realtime/realtime_response_status.py | 3 ++ tests/lib/test_realtime_response_status.py | 31 +++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 tests/lib/test_realtime_response_status.py diff --git a/src/openai/types/beta/realtime/realtime_response_status.py b/src/openai/types/beta/realtime/realtime_response_status.py index 7189cd58a1..986da1c8e4 100644 --- a/src/openai/types/beta/realtime/realtime_response_status.py +++ b/src/openai/types/beta/realtime/realtime_response_status.py @@ -12,6 +12,9 @@ class Error(BaseModel): code: Optional[str] = None """Error code, if any.""" + message: Optional[str] = None + """A human-readable description of the error, if any.""" + type: Optional[str] = None """The type of error.""" diff --git a/src/openai/types/realtime/realtime_response_status.py b/src/openai/types/realtime/realtime_response_status.py index 26b272ae5a..967e48886f 100644 --- a/src/openai/types/realtime/realtime_response_status.py +++ b/src/openai/types/realtime/realtime_response_status.py @@ -17,6 +17,9 @@ class Error(BaseModel): code: Optional[str] = None """Error code, if any.""" + message: Optional[str] = None + """A human-readable description of the error, if any.""" + type: Optional[str] = None """The type of error.""" diff --git a/tests/lib/test_realtime_response_status.py b/tests/lib/test_realtime_response_status.py new file mode 100644 index 0000000000..a4c2302f73 --- /dev/null +++ b/tests/lib/test_realtime_response_status.py @@ -0,0 +1,31 @@ +from __future__ import annotations + +from pydantic import BaseModel +import pytest + +from openai.types.beta.realtime import RealtimeResponseStatus as BetaRealtimeResponseStatus +from openai.types.realtime import RealtimeResponseStatus as RealtimeResponseStatus + + +@pytest.mark.parametrize( + "status_cls", + [BetaRealtimeResponseStatus, RealtimeResponseStatus], + ids=["beta", "realtime"], +) +def test_realtime_response_status_error_message(status_cls: type[BaseModel]) -> None: + status = status_cls.model_validate( + { + "error": { + "code": "bad_request", + "message": "The model could not process the request.", + "type": "invalid_request_error", + }, + "type": "failed", + } + ) + + assert status.error is not None + assert status.error.code == "bad_request" + assert status.error.message == "The model could not process the request." + assert status.error.type == "invalid_request_error" + assert status.type == "failed" From 8210df2da53d20c3f39e4178914722422079fd4c Mon Sep 17 00:00:00 2001 From: Muhtasim-Munif-Fahim Date: Mon, 8 Jun 2026 07:09:25 +0600 Subject: [PATCH 2/4] test: reproduce bare dict transform crash --- tests/test_transform.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/test_transform.py b/tests/test_transform.py index bece75dfc7..a5beb0015a 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -397,6 +397,18 @@ class DictItems(TypedDict): assert await transform({"foo": {"foo_baz": "bar"}}, Dict[str, DictItems], use_async) == {"foo": {"fooBaz": "bar"}} +class BareDictItems(TypedDict): + metadata: dict # pyright: ignore[reportMissingTypeArgument] + + +@parametrize +@pytest.mark.asyncio +async def test_bare_dict_annotation(use_async: bool) -> None: + assert await transform({"metadata": {"key": "value"}}, BareDictItems, use_async) == { + "metadata": {"key": "value"} + } + + class TypedDictIterableUnionStr(TypedDict): foo: Annotated[Union[str, Iterable[Baz8]], PropertyInfo(alias="FOO")] From 136d4ec6b43e1553573197bb4793e850d40bbbf6 Mon Sep 17 00:00:00 2001 From: Muhtasim-Munif-Fahim Date: Mon, 8 Jun 2026 07:09:39 +0600 Subject: [PATCH 3/4] fix: handle bare dict annotations in transform --- src/openai/_utils/_transform.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/openai/_utils/_transform.py b/src/openai/_utils/_transform.py index 414f38c340..f76e6113bc 100644 --- a/src/openai/_utils/_transform.py +++ b/src/openai/_utils/_transform.py @@ -180,7 +180,10 @@ def _transform_recursive( return _transform_typeddict(data, stripped_type) if origin == dict and is_mapping(data): - items_type = get_args(stripped_type)[1] + args = get_args(stripped_type) + if len(args) < 2: + return data + items_type = args[1] return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} if ( @@ -346,7 +349,10 @@ async def _async_transform_recursive( return await _async_transform_typeddict(data, stripped_type) if origin == dict and is_mapping(data): - items_type = get_args(stripped_type)[1] + args = get_args(stripped_type) + if len(args) < 2: + return data + items_type = args[1] return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} if ( From b92e9d3b5492be5197543cf5539e36ef546edd37 Mon Sep 17 00:00:00 2001 From: Muhtasim-Munif-Fahim Date: Mon, 8 Jun 2026 17:34:28 +0600 Subject: [PATCH 4/4] Handle bare dict types in construct_type --- src/openai/_models.py | 6 +++++- tests/test_models.py | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/openai/_models.py b/src/openai/_models.py index ed4c1f82d6..709b855e19 100644 --- a/src/openai/_models.py +++ b/src/openai/_models.py @@ -657,7 +657,11 @@ def construct_type(*, value: object, type_: object, metadata: Optional[List[Any] if not is_mapping(value): return value - _, items_type = get_args(type_) # Dict[_, items_type] + args = get_args(type_) + if len(args) < 2: + return value + + _, items_type = args # Dict[_, items_type] return {key: construct_type(value=item, type_=items_type) for key, item in value.items()} if ( diff --git a/tests/test_models.py b/tests/test_models.py index cc204bac1d..69a8abc93b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -133,6 +133,16 @@ class NestedModel(BaseModel): assert cast(Any, m.nested) is False +def test_bare_dictionary_passthrough() -> None: + bare = construct_type(value={"hello": {"foo": "bar"}}, type_=dict) + assert bare == {"hello": {"foo": "bar"}} + + typed = construct_type(value={"hello": {"foo": "bar"}}, type_=Dict[str, BasicModel]) + assert isinstance(typed, dict) + assert isinstance(typed["hello"], BasicModel) + assert typed["hello"].foo == "bar" + + def test_nested_dictionary_model() -> None: class NestedModel(BaseModel): nested: Dict[str, BasicModel]