You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Bug: output_serializer=PydanticSerializer crashes at import under from __future__ import annotations #8722
For contributors, human or agent. Comment here to claim this issue and wait for the assignment before opening a PR; if two PRs show up, the assignee's stays. AI-assisted work is welcome, say so in the PR and tell us how you verified it: run the tests yourself and paste what you saw, do not describe runs you did not do. Read AGENTS.md first, it has the commands and the rules the CI enforces. This goes into 3.41.0.
Expected Behaviour
output_serializer=PydanticSerializer (the class form, where the model is taken from the return annotation) works in a module that uses from __future__ import annotations, which is the default style in this repository and in most modern codebases.
Current Behaviour
Under PEP 563 the return annotation is a string, and idempotent_function passes function.__annotations__["return"] straight to PydanticSerializer.instantiate, which does issubclass(str, BaseModel) and raises TypeError: issubclass() arg 1 must be a class at decoration time, so the module fails to import. -> list[Model] has the same problem.
Code snippet
from __future__ importannotationsfrompydanticimportBaseModelfromaws_lambda_powertools.utilities.idempotencyimportidempotent_functionfromaws_lambda_powertools.utilities.idempotency.serialization.pydanticimportPydanticSerializerclassOrderOutput(BaseModel):
order_id: int@idempotent_function(data_keyword_argument="order", persistence_store=layer, output_serializer=PydanticSerializer)defprocess(order: dict) ->OrderOutput: # TypeError: issubclass() arg 1 must be a class, at importreturnOrderOutput(order_id=1)
Possible Solution
In aws_lambda_powertools/utilities/idempotency/idempotency.py, resolve the annotation with typing.get_type_hints(function).get("return") instead of reading __annotations__, and in serialization/pydantic.py guard instantiate with inspect.isclass so a non-class annotation raises IdempotencyModelTypeError with a clear message instead of TypeError. Add a test module that uses from __future__ import annotations and the class form, for a single model and for list[Model].
Item 5 of the Idempotency audit in #8603. No AWS resources needed.
For those interested in contributing, please leave a comment below so that we can assign the issue to you and make sure we don't duplicate efforts. If you have any further questions, please don't hesitate to ask below or on our Discord server.
Hi, I'd like to take this one. Plan: resolve the return annotation with typing.get_type_hints in idempotent_function, and guard PydanticSerializer.instantiate with inspect.isclass so a non-class annotation raises IdempotencyModelTypeError instead of TypeError. Tests go in a module with from __future__ import annotations, covering a single model and list[Model], and I'll confirm they fail on develop. I'm working with an AI assistant and will say so in the PR, along with the test output from my own runs.
Plan, following the suggestion in the description:
utilities/idempotency/idempotency.py: resolve the return annotation with typing.get_type_hints(function).get("return") instead of reading function.__annotations__, so PEP 563 string annotations are resolved before they reach the serializer.
utilities/idempotency/serialization/pydantic.py: guard instantiate with inspect.isclass so an annotation that is still not a class raises IdempotencyModelTypeError with a clear message instead of TypeError: issubclass() arg 1 must be a class.
Tests: a separate module using from __future__ import annotations with the class form of output_serializer=PydanticSerializer, for a single model and for list[Model], asserting decoration succeeds and the payload round-trips.
One thing I want to confirm while implementing: whether the list[Model] form is meant to be supported by PydanticSerializer as it stands, or whether the guard should reject it explicitly. I'll keep the change to what the issue describes unless you'd rather split it.
Verification I'll paste in the PR: the new tests failing on develop and passing with the fix, plus make lint and make mypy. This one needs no AWS resources, so there is no service-level validation to report.
Happy to wait for the assignment before opening a PR.
It resolves only the return annotation, so Annotated metadata, @no_type_check functions and unresolvable parameter annotations keep working. It also rejects parameterized aliases cleanly on Python 3.10. Tests pass locally on Python 3.10–3.14, including the minimum supported Pydantic version (2.4.0).
Activity
powertools-for-aws-oss-automation commentedon Oct 31, 2026
Note
For those interested in contributing, please leave a comment below so that we can assign the issue to you and make sure we don't duplicate efforts. If you have any further questions, please don't hesitate to ask below or on our Discord server.
sumedh-aerram commentedon Oct 31, 2026
Hi, I'd like to take this one. Plan: resolve the return annotation with
typing.get_type_hintsinidempotent_function, and guardPydanticSerializer.instantiatewithinspect.isclassso a non-class annotation raisesIdempotencyModelTypeErrorinstead ofTypeError. Tests go in a module withfrom __future__ import annotations, covering a single model andlist[Model], and I'll confirm they fail ondevelop. I'm working with an AI assistant and will say so in the PR, along with the test output from my own runs.inchang-ing commentedon Nov 1, 2026
I'd like to take this one.
Plan, following the suggestion in the description:
utilities/idempotency/idempotency.py: resolve the return annotation withtyping.get_type_hints(function).get("return")instead of readingfunction.__annotations__, so PEP 563 string annotations are resolved before they reach the serializer.utilities/idempotency/serialization/pydantic.py: guardinstantiatewithinspect.isclassso an annotation that is still not a class raisesIdempotencyModelTypeErrorwith a clear message instead ofTypeError: issubclass() arg 1 must be a class.from __future__ import annotationswith the class form ofoutput_serializer=PydanticSerializer, for a single model and forlist[Model], asserting decoration succeeds and the payload round-trips.One thing I want to confirm while implementing: whether the
list[Model]form is meant to be supported byPydanticSerializeras it stands, or whether the guard should reject it explicitly. I'll keep the change to what the issue describes unless you'd rather split it.Verification I'll paste in the PR: the new tests failing on
developand passing with the fix, plusmake lintandmake mypy. This one needs no AWS resources, so there is no service-level validation to report.Happy to wait for the assignment before opening a PR.
sumedh-aerram commentedon Nov 1, 2026
Following up on my earlier claim: I have a fix with regression tests ready on my fork, waiting for assignment before opening the PR: sumedh-aerram/powertools-lambda-python@develop...fix/idempotency-pydantic-serializer-future-annotations
It resolves only the return annotation, so
Annotatedmetadata,@no_type_checkfunctions and unresolvable parameter annotations keep working. It also rejects parameterized aliases cleanly on Python 3.10. Tests pass locally on Python 3.10–3.14, including the minimum supported Pydantic version (2.4.0).inchang-ing commentedon Nov 1, 2026
Withdrawing my claim. sumedh-aerram claimed this at 22:50 and already has a branch with regression tests ready, so this one is theirs.
I should have read the full comment history before claiming - I only checked the timeline for linked PRs. Sorry for the noise.
leandrodamascena commentedon Nov 1, 2026
@sumedh-aerram it's yours, assigning you now. Go ahead with the PR, and say in the description how you ran the tests.