Bug Report
Coroutine-local objects remain alive after ydb.aio.retry_operation propagates an application exception chained from a Pydantic ValidationError, even after the caller handles the exception and explicitly runs gc.collect(). No database connection is required to reproduce this.
YDB Python SDK version:
version 3.31.4
Environment
Environment: Python 3.12, Pydantic 2.13.4, pydantic-core 2.46.4.
Current behavior:
- Directly awaiting the same coroutine releases its local objects.
- Calling it through
ydb.aio.retry_operation retains them.
- A simple application exception without the validation-error cause did not reproduce the retention.
The observed reference chain is:
YdbRetryOperationFinalResult
→ application exception
→ Pydantic ValidationError
→ traceback
→ coroutine frame and local objects
Possible Pydantic-specific interaction: the reproduction uses a union of custom validators that raise ValueError. Pydantic can retain these underlying exceptions as validation-error context, potentially adding traceback references to the retry-state cycle. Its native implementation may be relevant to why the objects survive garbage collection, but this mechanism has not been established.
Expected behavior:
Once the operation has failed and the caller has handled the exception, otherwise-unreferenced coroutine locals should be collectible.
Steps to reproduce:
- Create a coroutine that allocates a local object and triggers a Pydantic validation error using a union of failing custom validators.
- Raise an application exception chained from that ValidationError.
- Compare directly awaiting the coroutine with calling it through ydb.aio.retry_operation.
- Handle the exception, run garbage collection, and check the local object through a weak reference.
- In the tested reproduction, the direct call released the object, while the SDK retry call retained it.
Bug Report
Coroutine-local objects remain alive after
ydb.aio.retry_operationpropagates an application exception chained from a Pydantic ValidationError, even after the caller handles the exception and explicitly runsgc.collect(). No database connection is required to reproduce this.YDB Python SDK version:
version
3.31.4Environment
Environment: Python 3.12, Pydantic 2.13.4, pydantic-core 2.46.4.
Current behavior:
ydb.aio.retry_operationretains them.The observed reference chain is:
Possible Pydantic-specific interaction: the reproduction uses a union of custom validators that raise
ValueError. Pydantic can retain these underlying exceptions as validation-error context, potentially adding traceback references to the retry-state cycle. Its native implementation may be relevant to why the objects survive garbage collection, but this mechanism has not been established.Expected behavior:
Once the operation has failed and the caller has handled the exception, otherwise-unreferenced coroutine locals should be collectible.
Steps to reproduce: