From 12681720e94a621a5b7e20520c4194611668dc3f Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 31 Jul 2026 09:09:04 +0200 Subject: [PATCH] fix: process image loading batch sequentially to avoid concurrent AsyncSession use SQLAlchemy async sessions are not safe for concurrent operations. load_series_images_batch was using asyncio.gather to run multiple load_series_images calls concurrently, all sharing the same db session. This caused 'session is provisioning a new connection; concurrent operations are not permitted' errors for every series in the batch. Fix by processing each batch sequentially instead of concurrently. BATCH_SIZE=10 still paces TMDB requests as intended. --- src/server/services/image_loading_service.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/server/services/image_loading_service.py b/src/server/services/image_loading_service.py index 7c27f6a..16e0a0b 100644 --- a/src/server/services/image_loading_service.py +++ b/src/server/services/image_loading_service.py @@ -162,17 +162,18 @@ class ImageLoadingService: for i in range(0, len(series_list), self.BATCH_SIZE): batch = series_list[i : i + self.BATCH_SIZE] - tasks = [ - self.load_series_images( + # Process each series sequentially to avoid concurrent use of the + # same AsyncSession (SQLAlchemy async sessions are not thread-safe + # for concurrent operations). BATCH_SIZE still paces TMDB requests. + results: List[Dict[str, Any] | Exception] = [] + for series in batch: + result = await self.load_series_images( key=series["key"], folder=series["folder"], anime_directory=anime_directory, db=db, ) - for series in batch - ] - - results = await asyncio.gather(*tasks, return_exceptions=True) + results.append(result) for series, result in zip(batch, results): if isinstance(result, Exception):