Skip to content

fix: guard against bare unparameterized dict/list in construct_type and transform#1639

Open
kiankhooban wants to merge 2 commits into
anthropics:mainfrom
kiankhooban:fix/bare-generic-type-crashes
Open

fix: guard against bare unparameterized dict/list in construct_type and transform#1639
kiankhooban wants to merge 2 commits into
anthropics:mainfrom
kiankhooban:fix/bare-generic-type-crashes

Conversation

@kiankhooban

Copy link
Copy Markdown

get_args(dict) and get_args(list) return empty tuples when no type parameters are present. Four sites were unconditionally indexing into those tuples, raising ValueError or IndexError when a model field is annotated as a bare dict or list instead of Dict[K, V] or List[T].

Crash sites fixed

src/anthropic/_models.py

src/anthropic/_utils/_transform.py

Fix

Guard each index access with a length check and fall back to object when no type args are present — preserving the value as-is, which is the correct behaviour for unparameterized containers.

Reproduction

from anthropic._models import construct_type
construct_type(value={"key": "value"}, type_=dict)  # was: ValueError
construct_type(value=["a", "b"], type_=list)         # was: IndexError

from anthropic._utils._transform import transform
transform({"key": "value"}, dict)                    # was: IndexError

Fixes #1619, #1626, #1628

…nd transform

get_args(dict) and get_args(list) return empty tuples when no type
parameters are present. Four sites were unconditionally indexing into
those tuples, crashing with ValueError or IndexError.

- _models.py: use already-computed `args` with len-guard for dict branch;
  add `if args` guard for list branch
- _utils/_transform.py: guard both sync and async dict branches

Fixes anthropics#1619, anthropics#1626, anthropics#1628
Copilot AI review requested due to automatic review settings June 3, 2026 22:47
@kiankhooban kiankhooban requested a review from a team as a code owner June 3, 2026 22:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Updates type-transformation utilities to handle unparameterized container annotations (e.g., dict / Dict without type args) more safely by defaulting inner types to object instead of indexing missing get_args() entries.

Changes:

  • Guard get_args() indexing for dict value types in recursive transform helpers.
  • Guard get_args() indexing for dict/list inner types in construct_type.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
src/anthropic/_utils/_transform.py Prevents IndexError when transforming dict-like data against dict annotations without type parameters.
src/anthropic/_models.py Makes construct_type robust to missing generic args for dict and list annotations by falling back to object.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/anthropic/_utils/_transform.py Outdated
Comment on lines 350 to 352
_args = get_args(stripped_type)
items_type = _args[1] if len(_args) >= 2 else object
return {key: _transform_recursive(value, annotation=items_type) for key, value in data.items()}
Comment thread src/anthropic/_utils/_transform.py Outdated
Comment on lines +183 to +184
_args = get_args(stripped_type)
items_type = _args[1] if len(_args) >= 2 else object
- Rename _args to args for consistency with rest of codebase
- Fix pre-existing bug: async dict branch was calling _transform_recursive
  instead of _async_transform_recursive, skipping async recursion for
  nested dict values; switch to await _async_transform_recursive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BUG: construct_type() crashes with ValueError when type_ is a bare dict

2 participants