fix: stop scan crashing on duplicate file hashes

scan.py used scalar_one_or_none() to test whether any other photo
shared the same file_hash, but that helper raises MultipleResultsFound
the moment 2+ rows match — i.e. exactly the duplicate case it was
trying to flag. Every file beyond the second copy bombed out with
"Multiple rows were found when one or none was required" and was
left in the failed bucket. Replace with a COUNT(*) > 0 check.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
root
2026-04-09 10:14:40 +02:00
parent 42250aa16e
commit 3df8add3b6

View File

@@ -11,7 +11,7 @@ import json
from typing import List, Dict, Optional
from celery import shared_task
from sqlalchemy import select
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession
import aiofiles
import redis
@@ -172,10 +172,21 @@ async def _scan_folder_async(folder_path: str, source_root_id: Optional[str], ta
# Calculate file hash for duplicate detection
file_hash = await calculate_file_hash(filepath)
# Check for duplicate by hash
duplicate = await session.execute(
select(Photo).where(Photo.file_hash == file_hash)
) if file_hash else None
# Check for duplicate by hash. We only care
# whether *any* other photo shares this hash, so
# use a count rather than scalar_one_or_none()
# which raises "Multiple rows were found" the
# moment the library has 2+ copies of the same
# file (i.e. exactly the case we're trying to
# flag).
is_dup = False
if file_hash:
dup_count = (await session.execute(
select(func.count(Photo.id)).where(
Photo.file_hash == file_hash
)
)).scalar() or 0
is_dup = dup_count > 0
# Create photo entry
photo = Photo(
@@ -188,7 +199,7 @@ async def _scan_folder_async(folder_path: str, source_root_id: Optional[str], ta
file_size=stat.st_size,
taken_at=datetime.fromtimestamp(stat.st_mtime),
taken_at_source='filesystem',
is_duplicate=bool(duplicate.scalar_one_or_none() if duplicate else False),
is_duplicate=is_dup,
processing_status='pending'
)