diff --git a/gns3server/db/repositories/images.py b/gns3server/db/repositories/images.py index de4e3c3d6..266f09997 100644 --- a/gns3server/db/repositories/images.py +++ b/gns3server/db/repositories/images.py @@ -47,8 +47,16 @@ class ImagesRepository(BaseRepository): where(models.Image.filename == image_name, models.Image.path.endswith(image_path)) else: query = select(models.Image).where(models.Image.filename == image_name) + query = query.order_by(models.Image.image_id) result = await self._db_session.execute(query) - return result.scalars().first() + images = result.scalars().all() + if len(images) > 1: + log.warning( + f"Multiple DB entries found for image '{image_path}' " + f"({len(images)} rows). This indicates a data integrity issue. " + f"Using the entry with the lowest image_id ({images[0].image_id})." + ) + return images[0] if images else None async def get_image_by_checksum(self, checksum: str, image_dir: str = None) -> Optional[models.Image]: """ diff --git a/gns3server/db/repositories/templates.py b/gns3server/db/repositories/templates.py index e4da33d2c..c141008d0 100644 --- a/gns3server/db/repositories/templates.py +++ b/gns3server/db/repositories/templates.py @@ -16,6 +16,7 @@ # along with this program. If not, see . import os +import logging from uuid import UUID from typing import List, Union, Optional @@ -29,6 +30,8 @@ from .base import BaseRepository import gns3server.db.models as models from gns3server import schemas +log = logging.getLogger(__name__) + TEMPLATE_TYPE_TO_MODEL = { "cloud": models.CloudTemplate, "docker": models.DockerTemplate, @@ -123,10 +126,16 @@ class TemplatesRepository(BaseRepository): where(models.Image.filename == image_name, models.Image.path.endswith(image_path)) else: query = select(models.Image).where(models.Image.filename == image_name) + query = query.order_by(models.Image.image_id) result = await self._db_session.execute(query) - # Use first() instead of one_or_none() to handle cases where multiple - # DB rows share the same filename (e.g. image discovered in multiple paths) - return result.scalars().first() + images = result.scalars().all() + if len(images) > 1: + log.warning( + f"Multiple DB entries found for image '{image_path}' " + f"({len(images)} rows). This indicates a data integrity issue. " + f"Using the entry with the lowest image_id ({images[0].image_id})." + ) + return images[0] if images else None async def add_image_to_template( self,