Skip to content

Conversation

@Jayyadav1903
Copy link

@Jayyadav1903 Jayyadav1903 commented Jan 21, 2026

PR: Fix Inconsistent AI Tagging Behavior

Summary

This PR improves the robustness of the AI tagging batch process by isolating failures at the image level. A single corrupted or unclassifiable image no longer crashes the entire tagging run.

Problem

The AI tagging pipeline previously failed inconsistently during batch processing. When the object classifier returned None (or raised an unexpected exception), a TypeError was triggered, terminating the entire loop. As a result:

  • Some images were silently skipped
  • The batch process stopped prematurely
  • Failures provided no actionable feedback

This behavior made the system unreliable and difficult to debug.

Solution

The image processing loop is now fault-tolerant. Errors are handled per image, logged explicitly, and do not affect the rest of the batch.

Implementation Details

File: backend/app/utils/images.py

Changes made:

  • Wrapped individual image processing logic in a try-except block.
  • Added an explicit guard for classes is None before accessing or iterating over results.
  • Logged failures at the image level, allowing problematic images to be skipped while processing continues.

Verification

  • Confirmed that classes is validated before length or index access.
  • Verified that exceptions raised for a single image are logged and do not interrupt the batch loop.
  • Ensured successful images in the same batch are still tagged correctly.

Scope

  • Backend-only change
  • No model or classification logic changes
  • No API or schema changes

Why this PR matters

  • Prevents entire batch failures due to edge-case images
  • Improves reliability and debuggability of AI tagging
  • Makes behavior predictable under real-world data conditions

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced error handling in image processing to gracefully manage individual image failures without stopping batch operations, with improved logging for troubleshooting.
  • New Features

    • Added smooth slide animations and close button to the media information panel for improved user interaction.
    • Implemented intelligent image classification and tagging with conditional face detection capabilities.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link
Contributor

⚠️ No issue was linked in the PR description.
Please make sure to link an issue (e.g., 'Fixes #issue_number')

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 21, 2026

📝 Walkthrough

Walkthrough

Backend image processing now includes per-image error handling, conditional face detection based on classification results, granular status updates, and resource cleanup. Frontend MediaInfoPanel adds animation support with slide transitions and reorganizes layout with a close button.

Changes

Cohort / File(s) Summary
Image Processing Enhancement
backend/app/utils/images.py
Adds inner try/except for individual image error handling; retrieves classification classes and conditionally triggers face detection (only when "person" class present, 1-6 count); inserts image-class pairs to database; updates image status post-processing; logs errors per image; extends finally block for resource cleanup
Media Info Panel Animation
frontend/src/components/Media/MediaInfoPanel.tsx
Integrates framer-motion AnimatePresence for panel animations (slide left on enter/exit); wraps content in motion.div with animated container; adds header bar with close button; reorganizes layout while preserving existing data extraction and file-open functionality

Sequence Diagram

sequenceDiagram
    participant App as Image Processing Loop
    participant Classifier as Object Classifier
    participant FaceDetector as Face Detector
    participant DB as Database
    participant Logger as Logger

    App->>Classifier: classify_image()
    alt Classification succeeds
        Classifier-->>App: return classes
        alt "person" class exists & count 1-6
            App->>FaceDetector: detect_faces()
            FaceDetector-->>App: return faces
            Note over App: Face detection complete
        else Skip face detection
            Note over App: No person class or count out of range
        end
        App->>DB: insert image-class pairs
        DB-->>App: success
        App->>Logger: log image-class pairs
        Logger-->>App: logged
        App->>App: update image status = tagged
    else Classification fails
        Classifier-->>App: return None
        App->>Logger: log classification error with path
        Logger-->>App: logged
        Note over App: Skip tagging, continue to next
    end
    Note over FaceDetector,Logger: finally: close classifier & face detector
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes


🐰 Hop hop, classes we detect,
Faces found with careful check,
Errors logged, no crash in sight,
Animations slide left, then right!
Smoother processing, oh what a treat! 🎬✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Fix/ai tagging inconsistency' is only partially related to the changeset; it refers to a real aspect of the change but obscures the main point with vague language. Consider a more specific title like 'Make AI tagging batch process fault-tolerant' or 'Add per-image error handling to prevent batch crash' to clearly convey the primary change.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Jayyadav1903
Copy link
Author

I would add a draft PR so that it can act as a reference.
The maintainers can also merge it after review if they deem it worthy.

@github-actions
Copy link
Contributor

⚠️ No issue was linked in the PR description.
Please make sure to link an issue (e.g., 'Fixes #issue_number')

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@backend/app/utils/images.py`:
- Around line 125-132: The db_insert_image_classes_batch call is not checked so
failures will still let the image be marked tagged; change the flow in the block
that creates image_class_pairs so you capture the return value of
db_insert_image_classes_batch(image_class_pairs), log an error/warning if it
returns False (including image_id and classes for context), and do not proceed
to the code that marks the image as tagged when the insert fails (either
return/raise or skip the status update); ensure db_insert_image_classes_batch,
image_class_pairs, classes and image_id are the anchors you use to locate and
change the logic.

In `@frontend/src/components/Media/MediaInfoPanel.tsx`:
- Around line 116-131: The conditional rendering currently uses a truthy check
on currentImage?.metadata?.latitude and longitude which will treat 0 as falsy
and hide valid coordinates; update the JSX conditional around currentImage to
explicitly check for null/undefined (e.g., currentImage?.metadata?.latitude !=
null && currentImage?.metadata?.longitude != null) so 0 values are allowed, and
keep using currentImage.metadata.latitude/toFixed and handleLocationClick only
inside that branch to avoid runtime errors.

Comment on lines +125 to +132
# Step 2: Insert class-image pairs if classes were detected
if len(classes) > 0:
# Create image-class pairs
image_class_pairs = [(image_id, class_id) for class_id in classes]
logger.debug(f"Image-class pairs: {image_class_pairs}")

# Insert the pairs into the database
db_insert_image_classes_batch(image_class_pairs)
# Insert the pairs into the database
db_insert_image_classes_batch(image_class_pairs)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Unchecked return value from db_insert_image_classes_batch may cause data inconsistency.

If the database insertion fails (returns False), processing continues and the image is still marked as tagged on line 139. This could leave the image in an inconsistent state—marked as tagged but with no class associations persisted.

Consider checking the return value and either skipping the status update or logging a warning on failure:

Suggested approach
                 # Insert the pairs into the database
-                db_insert_image_classes_batch(image_class_pairs)
+                if not db_insert_image_classes_batch(image_class_pairs):
+                    logger.warning(
+                        f"Failed to insert class associations for image {image_path}"
+                    )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Step 2: Insert class-image pairs if classes were detected
if len(classes) > 0:
# Create image-class pairs
image_class_pairs = [(image_id, class_id) for class_id in classes]
logger.debug(f"Image-class pairs: {image_class_pairs}")
# Insert the pairs into the database
db_insert_image_classes_batch(image_class_pairs)
# Insert the pairs into the database
db_insert_image_classes_batch(image_class_pairs)
# Step 2: Insert class-image pairs if classes were detected
if len(classes) > 0:
# Create image-class pairs
image_class_pairs = [(image_id, class_id) for class_id in classes]
logger.debug(f"Image-class pairs: {image_class_pairs}")
# Insert the pairs into the database
if not db_insert_image_classes_batch(image_class_pairs):
logger.warning(
f"Failed to insert class associations for image {image_path}"
)
🤖 Prompt for AI Agents
In `@backend/app/utils/images.py` around lines 125 - 132, The
db_insert_image_classes_batch call is not checked so failures will still let the
image be marked tagged; change the flow in the block that creates
image_class_pairs so you capture the return value of
db_insert_image_classes_batch(image_class_pairs), log an error/warning if it
returns False (including image_id and classes for context), and do not proceed
to the code that marks the image as tagged when the insert fails (either
return/raise or skip the status update); ensure db_insert_image_classes_batch,
image_class_pairs, classes and image_id are the anchors you use to locate and
change the logic.

Comment on lines +116 to +131
{currentImage?.metadata?.latitude &&
currentImage?.metadata?.longitude ? (
<button
type="button"
onClick={handleLocationClick}
className="flex w-full cursor-pointer items-center truncate text-left font-medium text-white hover:underline"
title={`Lat: ${currentImage.metadata.latitude}, Lon: ${currentImage.metadata.longitude}`}
>
{tag}
</span>
))}
{`Lat: ${currentImage.metadata.latitude.toFixed(4)}, Lon: ${currentImage.metadata.longitude.toFixed(4)}`}
<SquareArrowOutUpRight className="ml-1 h-[14px] w-[14px]" />
</button>
) : (
<p className="font-medium text-white">
Location not available
</p>
)}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Truthy check for coordinates may incorrectly hide valid (0, 0) locations.

The condition currentImage?.metadata?.latitude && currentImage?.metadata?.longitude treats 0 as falsy. While rare, coordinates at or near the equator (latitude 0) or prime meridian (longitude 0) would incorrectly show "Location not available."

Suggested fix using explicit null/undefined checks
-            {currentImage?.metadata?.latitude &&
-              currentImage?.metadata?.longitude ? (
+            {currentImage?.metadata?.latitude != null &&
+              currentImage?.metadata?.longitude != null ? (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{currentImage?.metadata?.latitude &&
currentImage?.metadata?.longitude ? (
<button
type="button"
onClick={handleLocationClick}
className="flex w-full cursor-pointer items-center truncate text-left font-medium text-white hover:underline"
title={`Lat: ${currentImage.metadata.latitude}, Lon: ${currentImage.metadata.longitude}`}
>
{tag}
</span>
))}
{`Lat: ${currentImage.metadata.latitude.toFixed(4)}, Lon: ${currentImage.metadata.longitude.toFixed(4)}`}
<SquareArrowOutUpRight className="ml-1 h-[14px] w-[14px]" />
</button>
) : (
<p className="font-medium text-white">
Location not available
</p>
)}
{currentImage?.metadata?.latitude != null &&
currentImage?.metadata?.longitude != null ? (
<button
type="button"
onClick={handleLocationClick}
className="flex w-full cursor-pointer items-center truncate text-left font-medium text-white hover:underline"
title={`Lat: ${currentImage.metadata.latitude}, Lon: ${currentImage.metadata.longitude}`}
>
{`Lat: ${currentImage.metadata.latitude.toFixed(4)}, Lon: ${currentImage.metadata.longitude.toFixed(4)}`}
<SquareArrowOutUpRight className="ml-1 h-[14px] w-[14px]" />
</button>
) : (
<p className="font-medium text-white">
Location not available
</p>
)}
🤖 Prompt for AI Agents
In `@frontend/src/components/Media/MediaInfoPanel.tsx` around lines 116 - 131, The
conditional rendering currently uses a truthy check on
currentImage?.metadata?.latitude and longitude which will treat 0 as falsy and
hide valid coordinates; update the JSX conditional around currentImage to
explicitly check for null/undefined (e.g., currentImage?.metadata?.latitude !=
null && currentImage?.metadata?.longitude != null) so 0 values are allowed, and
keep using currentImage.metadata.latitude/toFixed and handleLocationClick only
inside that branch to avoid runtime errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant