AsyncFinalizerInSyncCloseError¶
Symptom¶
close_sync() raises a FinalizerError, and one of its .exceptions is an
AsyncFinalizerInSyncCloseError:
+ Exception Group Traceback (most recent call last):
| ...
| modern_di.exceptions.lifecycle.FinalizerError: Container.close_sync() found 1 finalizer error(s): AsyncFinalizerInSyncCloseError (1)
| See: https://modern-di.modern-python.org/troubleshooting/finalizer-error/
+-+---------------- 1 ----------------
| modern_di.exceptions.lifecycle.AsyncFinalizerInSyncCloseError: Cannot run async finalizer for AsyncResource during sync close. Use `await container.close_async()` (or `async with container:`) instead.
| See: https://modern-di.modern-python.org/troubleshooting/async-finalizer-in-sync-close-error/
+------------------------------------
.instance_type holds the type of the cached instance, and except* AsyncFinalizerInSyncCloseError
catches it.
Cause¶
close_sync() cannot await. It records this error for a cached instance whose finalizer is an
async def, and for one whose sync finalizer returns an awaitable. In both cases it keeps the
instance cached, unlike a finalizer that raised, whose instance is dropped. While the instance stays
cached, a repeated close_sync() reports it again, and resolving after a reopen returns the same
instance.
Fix¶
Close the container with close_async() or async with container:, the only paths that can run an
async finalizer. After a close_sync() that reported this error, await container.close_async()
runs the finalizer and finishes the cleanup:
container.resolve(AsyncResource)
try:
container.close_sync()
except* exceptions.AsyncFinalizerInSyncCloseError:
pass # AsyncResource is still cached
await container.close_async() # runs close_resource
Use close_sync() only for containers you know hold no async finalizer.
See also¶
- Lifecycle: async finalizers and
close_sync()— howclose_sync()treats an async finalizer. - FinalizerError — the group this error arrives in.