From d4176fd3d094a0646d3ba1034c9f075c8194f3ff Mon Sep 17 00:00:00 2001 From: devteamaegis Date: Sun, 31 May 2026 23:26:26 -0400 Subject: [PATCH] fix: guard bare dict annotation in _transform_recursive to avoid IndexError MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When `_transform_recursive` (sync and async) receives a bare `dict` annotation (not `Dict[K, V]`), `get_args(dict)` returns `()` so indexing `[1]` raises `IndexError: tuple index out of range`. Guard the index with `len(args) >= 2`, falling back to `Any` for unparameterized dicts — matching the pattern already used in `_models.py`. Co-Authored-By: claude-flow --- src/anthropic/_utils/_transform.py | 6 ++++-- tests/test_transform.py | 9 +++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/anthropic/_utils/_transform.py b/src/anthropic/_utils/_transform.py index 1e7e5ac80..cdf59c531 100644 --- a/src/anthropic/_utils/_transform.py +++ b/src/anthropic/_utils/_transform.py @@ -180,7 +180,8 @@ 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) + items_type = args[1] if len(args) >= 2 else Any return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} if ( @@ -346,7 +347,8 @@ 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) + items_type = args[1] if len(args) >= 2 else Any return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()} if ( diff --git a/tests/test_transform.py b/tests/test_transform.py index 4a874ff86..a1a2e8a03 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -458,3 +458,12 @@ async def test_strips_notgiven(use_async: bool) -> None: async def test_strips_omit(use_async: bool) -> None: assert await transform({"foo_bar": "bar"}, Foo1, use_async) == {"fooBar": "bar"} assert await transform({"foo_bar": omit}, Foo1, use_async) == {} + + +@parametrize +@pytest.mark.asyncio +async def test_transform_recursive_bare_dict_no_index_error(use_async: bool) -> None: + # A bare (unparameterized) `dict` annotation must not raise IndexError when + # get_args(dict) returns () and the code tries to index position [1]. + result = await transform({"key": "value"}, dict, use_async) + assert result == {"key": "value"}