Skip to content

fix(availability-sync): keep seasons when the media server is unreachable#3102

Open
OmarB97 wants to merge 4 commits into
seerr-team:developfrom
OmarB97:fix/availability-sync-keep-seasons-when-media-server-unreachable
Open

fix(availability-sync): keep seasons when the media server is unreachable#3102
OmarB97 wants to merge 4 commits into
seerr-team:developfrom
OmarB97:fix/availability-sync-keep-seasons-when-media-server-unreachable

Conversation

@OmarB97

@OmarB97 OmarB97 commented Jun 2, 2026

Copy link
Copy Markdown

Description

Fixes #1729.

This PR stops availability sync from marking TV seasons as deleted when Plex or Jellyfin is temporarily unreachable. If the media-server lookup fails with a non-404 error, seasons that were already available stay available instead of being treated as missing.

The net effect of this is that instead of Seerr showing the show that DOES exist on Plex as deleted (even though it's not deleted), NOW it will show as available (synced).

How Has This Been Tested?

Added regression coverage for Plex and Jellyfin outage cases.

Screenshots / Logs (if applicable)

N/A

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)

AI Disclosure

AI assistance was used while working on this PR. I reviewed the changes before submitting them.

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved handling of TV season availability when media server connections fail with non-404 errors
    • Fixed season verification logic during availability sync to properly filter and process seasons
  • Tests

    • Added regression tests for media server connection error scenarios

…able

A non-404 error while checking a show in Plex/Jellyfin sets existsInPlex /
existsInJellyfin = true to protect the show ("Preventing removal"), but the
returned season map is left empty. The caller seeds every available season to
"false" and only flips it to "true" on an affirmative find, so an empty map is
treated as "all seasons absent" and seasonUpdater marks them DELETED -- even
though the media still exists and we only failed to reach the server. The
preventSeasonSearch guard previously just skipped the (already-empty-on-error)
season loop, so it did not change this outcome.

Mirror the show-level guard at the season level: when the lookup errors, assume
the previously-available seasons still exist rather than returning an empty map.
A genuine 404 still falls through to normal detection, and a successful-but-empty
response still deletes as before.

Adds a regression test covering a Plex connection failure with no Sonarr coverage.

Closes seerr-team#1729
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@OmarB97 OmarB97 requested a review from a team as a code owner June 2, 2026 03:55
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4d44f1a0-1596-4337-a986-c4996b2f01bc

📥 Commits

Reviewing files that changed from the base of the PR and between 8572f42 and 881106b.

📒 Files selected for processing (1)
  • server/lib/availabilitySync.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • server/lib/availabilitySync.ts

📝 Walkthrough

Walkthrough

Fixes season-map building in Plex and Jellyfin TV sync paths so filtered seasons are always recorded when season checks are suppressed; adds Jest regression tests that simulate non-404 connection refusals and assert shows and seasons remain AVAILABLE.

Changes

Season Availability Sync Fix

Layer / File(s) Summary
Season existence maps for Plex and Jellyfin
server/lib/availabilitySync.ts
mediaExistsInPlex and mediaExistsInJellyfin now filter eligible TV seasons and populate seasonsMap. If preventSeasonSearch is true each filtered season is marked as existing; otherwise per-season checks populate the map. Previously the map could be left empty when checks were suppressed.
Regression tests for connection error handling
server/lib/availabilitySync.test.ts
Adds Jest tests mocking Jellyfin and Plex metadata/season fetches to throw non-404 connection errors while TMDB reports all seasons and Sonarr lookup returns 404; asserts availabilitySync preserves the show and all seasons as MediaStatus.AVAILABLE.

Sequence Diagram(s)

sequenceDiagram
  participant AvailabilitySync
  participant Plex
  participant Jellyfin
  participant TMDB
  participant Sonarr
  AvailabilitySync->>Plex: filter TV seasons by 4K status / build seasons list
  AvailabilitySync->>Jellyfin: filter TV seasons by 4K status / build seasons list
  alt preventSeasonSearch == true
    AvailabilitySync->>AvailabilitySync: mark filtered seasons as existing in seasonsMap
  else preventSeasonSearch == false
    AvailabilitySync->>Plex: call seasonExistsInPlex for each season
    Plex-->>AvailabilitySync: season existence result
    AvailabilitySync->>Jellyfin: call seasonExistsInJellyfin for each season
    Jellyfin-->>AvailabilitySync: season existence result
  end
  AvailabilitySync->>TMDB: fetch show/season metadata
  AvailabilitySync->>Sonarr: attempt series lookup (may 404)
  Sonarr-->>AvailabilitySync: lookup result
  AvailabilitySync->>AvailabilitySync: finalize statuses for show and seasons
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • seerr-team/seerr#2850: Both PRs modify server/lib/availabilitySync.ts logic for per-season existence evaluation and error/connection-failure handling.

Suggested labels

bug, severity: critical

Suggested reviewers

  • fallenbagel
  • gauthier-th
  • 0xSysR3ll

Poem

🐰 I tunneled through tests to keep each season whole,

When servers refused, I guarded every role.
Maps stayed filled, no season went away,
The rabbit hops happy — availability will stay.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main fix: preventing seasons from being marked as deleted when the media server is unreachable.
Linked Issues check ✅ Passed The PR implementation directly addresses the core requirements from issue #1729: preserving seasons when media-server lookups fail with non-404 errors while maintaining correct deletion semantics for legitimate absences.
Out of Scope Changes check ✅ Passed All changes are scoped to the availability sync logic: implementing the fix for non-404 failures and adding regression tests for Plex and Jellyfin outage scenarios.

✏️ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)

902-977: ⚡ Quick win

Add the matching Jellyfin non-404 outage regression case.

This new test locks the Plex path well, but this PR also changes the same fallback contract in mediaExistsInJellyfin. Adding the analogous Jellyfin test (metadata/season fetch throws non-404, Sonarr 404, TMDB seasons present) would protect cross-provider behavior from drifting.

Suggested test shape
+ it('should not delete seasons when Jellyfin fetch fails with a non-404 error', async () => {
+   configureJellyfin();
+   configureSonarr([{ syncEnabled: true }]);
+   // seed TV media with AVAILABLE seasons
+   // mock getItemData/getSeasons to throw non-404 connection error
+   // mock Sonarr getSeriesById -> 404
+   // mock TMDB seasons present
+   // run sync and assert all seasons + show remain AVAILABLE
+ });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@server/lib/availabilitySync.test.ts` around lines 902 - 977, Add a parallel
regression test for Jellyfin mirroring the Plex case: create a test similar to
the Plex "should not delete seasons when the Plex season fetch fails with a
non-404 error" but exercising mediaExistsInJellyfin instead — configure the show
with MediaType.TV and a Jellyfin ratingKey, make the Jellyfin metadata/children
fetch implementations throw a non-404 connection error, make getSeriesByIdImpl
throw a 404, have getTvShowImpl return TMDB seasons with episodes, run
availabilitySync.run, and assert the show's status and each Season.status remain
MediaStatus.AVAILABLE; use the existing Plex test as the template and reference
symbols mediaExistsInJellyfin, availabilitySync.run, getSeriesByIdImpl, and
getTvShowImpl to locate where to add the new case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@server/lib/availabilitySync.test.ts`:
- Around line 902-977: Add a parallel regression test for Jellyfin mirroring the
Plex case: create a test similar to the Plex "should not delete seasons when the
Plex season fetch fails with a non-404 error" but exercising
mediaExistsInJellyfin instead — configure the show with MediaType.TV and a
Jellyfin ratingKey, make the Jellyfin metadata/children fetch implementations
throw a non-404 connection error, make getSeriesByIdImpl throw a 404, have
getTvShowImpl return TMDB seasons with episodes, run availabilitySync.run, and
assert the show's status and each Season.status remain MediaStatus.AVAILABLE;
use the existing Plex test as the template and reference symbols
mediaExistsInJellyfin, availabilitySync.run, getSeriesByIdImpl, and
getTvShowImpl to locate where to add the new case.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: befdb0d2-3c91-4be3-b653-ba2abdbd8372

📥 Commits

Reviewing files that changed from the base of the PR and between 63175f5 and 1f71fb7.

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

Mirror of the Plex outage regression test for the Jellyfin/Emby path, since
the fix applies the same fallback contract to mediaExistsInJellyfin. Verified
it fails without the change (seasons become DELETED) and passes with it.

Addresses CodeRabbit review feedback on seerr-team#3102.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@fallenbagel fallenbagel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Few changes requested.

Also a nitpick:
The inline comments explaining the test scenario are a bit much. The test name and the mock setup are self-explanatory enough. Would prefer to trim these comments down.

Comment thread server/lib/availabilitySync.ts Outdated
Comment thread server/lib/availabilitySync.ts Outdated
@M0NsTeRRR

Copy link
Copy Markdown
Member

@OmarB97 Rule number 1 from our CONTRIBUTING.md.

PR descriptions and all comments must be your own words. Do not paste LLM output as your PR description, review response, or issue comment. We want your understanding and explanation of the changes, not a machine-generated summary. An exception is made for LLM-assisted translation, however, note it explicitly if used.

Don’t copy/paste unnecessary sentences. The CI handles tests no need to share results, we won’t trust them.

@OmarB97

OmarB97 commented Jun 2, 2026

Copy link
Copy Markdown
Author

Removed the generated PR/comment text.

The bug is that a Plex/Jellyfin outage preserves the show but leaves the season map empty, so seasons get marked deleted. This PR keeps already-available seasons available when the media server lookup fails with a non-404 error.

Let me know if you have any other issues/concerns.

Comment thread server/lib/availabilitySync.ts
Comment thread server/lib/availabilitySync.ts
@OmarB97

OmarB97 commented Jun 2, 2026

Copy link
Copy Markdown
Author

addressed comments above. captured the full relevant context in each of those comments without being overly verbose.

@seerr-automation-bot seerr-automation-bot added this to the v3.3.1 milestone Jun 2, 2026
@fallenbagel fallenbagel modified the milestones: v3.3.1, v3.4.0 Jun 4, 2026
@gauthier-th

Copy link
Copy Markdown
Member

@0xSysR3ll could you please test if you can reproduce the root issue of this? And test if this PR fixes it if you can reproduce?

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.

Availability Sync marks seasons as "deleted" and shows as "partially available"

5 participants