Skip to content

fix(availability-sync): detect deleted seasons when media server retains empty season metadata#2850

Open
fallenbagel wants to merge 4 commits intodevelopfrom
fallenbagel/fix/debug-availability-sync-job
Open

fix(availability-sync): detect deleted seasons when media server retains empty season metadata#2850
fallenbagel wants to merge 4 commits intodevelopfrom
fallenbagel/fix/debug-availability-sync-job

Conversation

@fallenbagel
Copy link
Copy Markdown
Collaborator

@fallenbagel fallenbagel commented Apr 9, 2026

Description

The availability sync was not detecting deleted seasons on Jellyfin
(and potentially Plex), causing them to stay marked as AVAILABLE even
after all episode files were removed from the media server. Users were
unable to re-request these seasons.

The issue was that Jellyfin's /Shows/{id}/Seasons endpoint sometimes returned
season metadata entries even when every episode in that season has been
deleted. The season existence check only looked for a matching season
metadata entry, so it always returned true for every season the media
server knew about, regardless of whether any files actually existed.
This overrode the correctly computed "not available" state from the
filtered seasons map, preventing the season updater from ever firing.

Debug logging on a similar scenario confirmed this for a Show instance (TMDB 1408):
Jellyfin returned all 9 season entries, Sonarr correctly reported only
season 6, but the Jellyfin result overwrote everything in the final
seasons map.

The fix adds an episode-level check in both seasonExistsInJellyfin
and seasonExistsInPlex. After finding a season metadata entry, the
sync now fetches the season's episodes and confirms at least one
non-virtual episode exists before marking the season as available.
On API error, it defaults to assuming the season exists to avoid
false removal.

How Has This Been Tested?

  • This was tested by a user on discord and confirmed as working (Jellyfin)
  • Not tested on Plex instance but unit tests passes

Screenshots / Logs (if applicable)

Checklist:

  • I have read and followed the contribution guidelines.
  • Disclosed any use of AI (see our policy)
  • I have updated the documentation accordingly.
  • All new and existing tests passed.
  • Successful build pnpm build
  • Translation keys pnpm i18n:extract
  • Database migration (if required)

Summary by CodeRabbit

  • Bug Fixes

    • More accurate season existence checks for Plex and Jellyfin by verifying actual episode data per season, with per-sync caching and safe fallbacks that assume existence if episode retrieval fails to avoid accidental removals; handles cases where Sonarr linkage is absent.
  • Tests

    • Added comprehensive availability sync tests covering Jellyfin, Plex, and Sonarr scenarios and edge cases.

@fallenbagel fallenbagel requested a review from Copilot April 9, 2026 23:07
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Adds per-sync caches and per-season episode checks for Plex and Jellyfin in availability sync (with safe "assume exists" fallback on fetch errors) and introduces a comprehensive test suite that exercises Plex/Jellyfin/Sonarr scenarios for season deletion and status transitions.

Changes

Cohort / File(s) Summary
Test Suite
server/lib/availabilitySync.test.ts
New end-to-end style tests: module-level mocks for Jellyfin/Plex/Sonarr, helpers to synthesize show/season/episode metadata and Sonarr stats, scenarios verifying season deletion, partial availability, and safe fallback behaviors.
Season Existence Validation
server/lib/availabilitySync.ts
Add per-sync caches (plexEpisodeExistsCache, jellyfinEpisodeExistsCache); update seasonExistsInPlex to require non-empty getChildrenMetadata media and memoize by ratingKey (assume exists on error); update seasonExistsInJellyfin to require non-empty getEpisodes and memoize by ${seriesId}-${seasonId} (assume exists on error).

Sequence Diagram(s)

sequenceDiagram
    participant Sync as AvailabilitySync
    participant MS as Media Server (Plex / Jellyfin)
    participant DB as Database

    Sync->>DB: Load shows & seasons with metadata refs
    loop for each season
        Sync->>MS: Fetch season metadata
        alt metadata missing
            MS-->>Sync: Not found
            Sync->>DB: Mark season DELETED
        else metadata found
            Sync->>MS: Fetch season's episodes/children
            alt episodes found (non-empty)
                MS-->>Sync: Episode list (non-empty)
                Sync->>DB: Mark season AVAILABLE
            else episodes empty
                MS-->>Sync: Empty list
                Sync->>DB: Mark season DELETED
            else fetch error
                MS-->>Sync: Error
                Sync->>DB: Mark season AVAILABLE (safe fallback)
            end
        end
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

bug, severity: medium

Suggested reviewers

  • gauthier-th
  • 0xSysR3ll

Poem

🐇 I hopped through metadata, sniffed each trace,
Found seasons missing from their usual place.
I mark what’s gone, but if errors confound,
I err on safety so shows stay sound.
A tidy sync — a rabbit's happy pace.

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix: detecting deleted seasons when media servers retain empty season metadata, which aligns with the core change of adding episode-level existence checks to prevent false AVAILABLE statuses.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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


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.

@fallenbagel fallenbagel changed the title Fallenbagel/fix/debug availability sync job fix(availability-sync): detect deleted seasons when media server retains empty season metadata Apr 9, 2026
@seerr-automation-bot seerr-automation-bot added this to the v3.2.0 milestone Apr 9, 2026
Copy link
Copy Markdown

@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.

🧹 Nitpick comments (1)
server/lib/availabilitySync.test.ts (1)

227-241: Nitpick: Episode type should be 'episode' not 'movie'.

The type field is set to 'movie' for what represents episode data. While this doesn't affect the current tests (since only length is checked), it's semantically incorrect and could cause confusion or issues if future tests need to validate episode types.

🔧 Suggested fix
 function fakePlexEpisodes(count: number): PlexMetadata[] {
   return Array.from({ length: count }, (_, i) => ({
     ratingKey: `ep-${i}`,
     guid: `plex://episode/ep-${i}`,
-    type: 'movie' as const,
+    type: 'episode' as const,
     title: `Episode ${i + 1}`,
     Guid: [],
     index: i + 1,
     leafCount: 0,
     viewedLeafCount: 0,
     addedAt: 0,
     updatedAt: 0,
     Media: [],
   }));
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/lib/availabilitySync.test.ts` around lines 227 - 241, The
fakePlexEpisodes helper creates PlexMetadata items with type set incorrectly to
'movie'; update the type field in fakePlexEpisodes (the object returned in the
Array.from) from 'movie' to 'episode' (and adjust the literal/type assertion if
present) so the fake episode fixtures correctly reflect episode metadata for
future tests that inspect type.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@server/lib/availabilitySync.test.ts`:
- Around line 227-241: The fakePlexEpisodes helper creates PlexMetadata items
with type set incorrectly to 'movie'; update the type field in fakePlexEpisodes
(the object returned in the Array.from) from 'movie' to 'episode' (and adjust
the literal/type assertion if present) so the fake episode fixtures correctly
reflect episode metadata for future tests that inspect type.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2c245b3d-3f42-498c-b7b2-1adbdd5e7143

📥 Commits

Reviewing files that changed from the base of the PR and between 061121c and 4b60278.

📒 Files selected for processing (2)
  • server/lib/availabilitySync.test.ts
  • server/lib/availabilitySync.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes the availability sync job incorrectly keeping TV seasons marked AVAILABLE when the media server returns season metadata despite all episode files being removed, preventing users from re-requesting those seasons.

Changes:

  • Update Plex season existence detection to verify a season has episodes before treating it as present.
  • Update Jellyfin season existence detection to verify a season has at least one non-virtual episode before treating it as present.
  • Add a comprehensive unit test suite covering Jellyfin/Plex deleted-season scenarios and safe fallbacks on API failures.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
server/lib/availabilitySync.ts Adds episode-level existence checks for Plex/Jellyfin seasons to avoid stale AVAILABLE seasons after episode deletion.
server/lib/availabilitySync.test.ts Adds unit tests validating deleted-season detection and error fallback behavior for both Jellyfin and Plex.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/lib/availabilitySync.ts Outdated
Comment thread server/lib/availabilitySync.ts Outdated
Comment thread server/lib/availabilitySync.test.ts
Comment thread server/lib/availabilitySync.ts Outdated
@fallenbagel fallenbagel requested a review from a team as a code owner April 9, 2026 23:21
@fallenbagel fallenbagel force-pushed the fallenbagel/fix/debug-availability-sync-job branch from 04a1bcd to 47dabcb Compare April 9, 2026 23:24
@seerr-automation-bot seerr-automation-bot modified the milestones: v3.2.0, v3.2.1 Apr 15, 2026
Copy link
Copy Markdown
Member

@gauthier-th gauthier-th left a comment

Choose a reason for hiding this comment

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

LGTM

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.

4 participants