Skip to content

Bug: output_serializer=PydanticSerializer crashes at import under from __future__ import annotations #8722

Open

Description

@leandrodamascena

Warning

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__ import annotations

from pydantic import BaseModel
from aws_lambda_powertools.utilities.idempotency import idempotent_function
from aws_lambda_powertools.utilities.idempotency.serialization.pydantic import PydanticSerializer

class OrderOutput(BaseModel):
    order_id: int

@idempotent_function(data_keyword_argument="order", persistence_store=layer, output_serializer=PydanticSerializer)
def process(order: dict) -> OrderOutput:  # TypeError: issubclass() arg 1 must be a class, at import
    return OrderOutput(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.

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.13

Packaging format used

PyPi

Debugging logs

No response

Activity

  1. added this to the 3.41.0 milestone on Oct 31, 2026
  2. powertools-for-aws-oss-automation commented on Oct 31, 2026

    @powertools-for-aws-oss-automation

    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.

  3. sumedh-aerram commented on Oct 31, 2026

    @sumedh-aerram

    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.

  4. inchang-ing commented on Nov 1, 2026

    @inchang-ing

    I'd like to take this one.

    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.

  5. sumedh-aerram commented on Nov 1, 2026

    @sumedh-aerram

    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 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).

  6. inchang-ing commented on Nov 1, 2026

    @inchang-ing

    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.

  7. leandrodamascena commented on Nov 1, 2026

    @leandrodamascena
    ContributorAuthor

    @sumedh-aerram it's yours, assigning you now. Go ahead with the PR, and say in the description how you ran the tests.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workinggood first issueGood for newcomershelp wantedCould use a second pair of eyes/handsidempotencyIdempotency utility

Type

No type

Projects

Relationships

None yet

Development

No branches or pull requests

Issue actions