Skip to content

fix: add TheMovieDb provider fallback for Jellyfin scanner#2605

Open
YakGravity wants to merge 8 commits intoseerr-team:developfrom
YakGravity:fix/jellyfin-themoviedb-provider-fallback
Open

fix: add TheMovieDb provider fallback for Jellyfin scanner#2605
YakGravity wants to merge 8 commits intoseerr-team:developfrom
YakGravity:fix/jellyfin-themoviedb-provider-fallback

Conversation

@YakGravity
Copy link

@YakGravity YakGravity commented Feb 28, 2026

Description

Shokofin (a Jellyfin plugin for anime managed by Shoko Server) writes TMDB IDs using the legacy Jellyfin provider key TheMovieDb instead of Tmdb. This causes Seerr to miss all anime managed by Shokofin during library sync, showing them as unavailable despite being present in Jellyfin.

This PR adds a fallback in three places in the Jellyfin scanner:

  1. Movie scanner (extractMovieIds): metadata.ProviderIds.Tmdb || metadata.ProviderIds.TheMovieDb || null
  2. TV show scanner (processJellyfinShow): Added || metadata.ProviderIds.TheMovieDb to the if-condition
  3. TV show scanner (processJellyfinShow): Number(metadata.ProviderIds.Tmdb || metadata.ProviderIds.TheMovieDb) for the tmdbId lookup

No breaking changes: When Tmdb exists (standard Sonarr/Radarr), || short-circuits and behavior is unchanged. The fallback only activates for items using the legacy TheMovieDb key.

How Has This Been Tested?

Tested on a live Jellyfin + Shokofin setup with multiple anime titles. Before the fix, all Shokofin-managed anime showed as unavailable in Seerr. After the fix, library sync correctly identifies them (e.g. "Frieren: Beyond Journey's End" returns mediaInfo.status: 4 PARTIALLY_AVAILABLE). Non-anime content (Sonarr/Radarr managed) continues to work without regression.

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

The root cause analysis (Shokofin using TheMovieDb vs Tmdb provider key) was identified through manual debugging with log analysis. Claude was consulted for reviewing the fix approach and drafting the PR description. The code changes were authored and tested manually.

Summary by CodeRabbit

  • Bug Fixes
    • Jellyfin integration now recognizes alternate TMDb identifier keys for movies and TV shows, improving ID derivation and metadata matching.
    • Library scans are more reliable when metadata uses different TMDb provider fields, reducing missed or incorrect media matches.

Shokofin writes TMDB IDs using the legacy Jellyfin provider key
"TheMovieDb" instead of "Tmdb". This causes Seerr to miss all
anime managed by Shokofin during library sync, showing them as
unavailable despite being present in Jellyfin.

Adds nullish coalescing fallback (Tmdb ?? TheMovieDb) in three
places in the Jellyfin scanner for both movie and TV show
processing.
@YakGravity YakGravity requested a review from a team as a code owner February 28, 2026 17:06
@coderabbitai
Copy link

coderabbitai bot commented Feb 28, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Update in the Jellyfin scanner to derive tmdbId from metadata.ProviderIds.Tmdb with a fallback to metadata.ProviderIds.TheMovieDb, and to use that fallback when passing the TMDb ID into TV show lookup.

Changes

Cohort / File(s) Summary
Jellyfin Scanner TMDb ID Fallback
server/lib/scanners/jellyfin/index.ts
Compute tmdbId from metadata.ProviderIds.Tmdb or fallback to metadata.ProviderIds.TheMovieDb; apply same fallback when extracting IDs for movies and when calling getTvShow for shows.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested labels

bug, severity: medium

Suggested reviewers

  • gauthier-th
  • 0xSysR3ll

Poem

🐰 I hop through metadata, light and spry,
I peek at Tmdb, then TheMovieDb if dry.
When one key's missing, the other I try,
IDs resolved — I twirl and sigh!

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: adding a TheMovieDb provider fallback for the Jellyfin scanner to handle legacy provider keys.

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

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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.

Copy link

@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/scanners/jellyfin/index.ts (1)

230-233: Consider using || instead of ?? for consistency with the condition.

Line 230 uses || (falsy check), while line 233 uses ?? (nullish check). If Tmdb were an empty string and TheMovieDb had a valid ID, the condition would pass but Number("") would yield 0.

This is likely an edge case since Jellyfin provider IDs are typically either present with values or absent, but using || on line 233 would match the condition's semantics.

Suggested change for consistency
       if (metadata.ProviderIds.Tmdb || metadata.ProviderIds.TheMovieDb) {
         try {
           tvShow = await this.getTvShow({
-            tmdbId: Number(metadata.ProviderIds.Tmdb ?? metadata.ProviderIds.TheMovieDb),
+            tmdbId: Number(metadata.ProviderIds.Tmdb || metadata.ProviderIds.TheMovieDb),
           });
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/lib/scanners/jellyfin/index.ts` around lines 230 - 233, The condition
checks metadata.ProviderIds.Tmdb || metadata.ProviderIds.TheMovieDb but the call
to this.getTvShow uses the nullish coalescing operator
(metadata.ProviderIds.Tmdb ?? metadata.ProviderIds.TheMovieDb); change that to
use the logical OR (metadata.ProviderIds.Tmdb ||
metadata.ProviderIds.TheMovieDb) so the chosen value matches the condition
semantics before calling Number(...) in the getTvShow invocation.
🤖 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/scanners/jellyfin/index.ts`:
- Around line 230-233: The condition checks metadata.ProviderIds.Tmdb ||
metadata.ProviderIds.TheMovieDb but the call to this.getTvShow uses the nullish
coalescing operator (metadata.ProviderIds.Tmdb ??
metadata.ProviderIds.TheMovieDb); change that to use the logical OR
(metadata.ProviderIds.Tmdb || metadata.ProviderIds.TheMovieDb) so the chosen
value matches the condition semantics before calling Number(...) in the
getTvShow invocation.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f74306e and d9e69cb.

📒 Files selected for processing (1)
  • server/lib/scanners/jellyfin/index.ts

@fallenbagel
Copy link
Collaborator

Please update your pr description with the proper pr template. You're missing several things from the checklist.

Copy link

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@server/lib/scanners/jellyfin/index.ts`:
- Line 63: The tmdbId assignment uses the nullish coalescing operator (??) which
differs from other checks (lines using ||) and will not fallback when
ProviderIds.Tmdb is an empty string; update the assignment for tmdbId to use the
logical OR operator so it falls back to metadata.ProviderIds.TheMovieDb for
falsy values (empty string, 0, undefined, null) before calling Number, i.e.,
replace the ?? between metadata.ProviderIds.Tmdb and
metadata.ProviderIds.TheMovieDb with || so the behavior is consistent with the
other checks.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d9e69cb and 03e45d4.

📒 Files selected for processing (1)
  • server/lib/scanners/jellyfin/index.ts

fallenbagel
fallenbagel previously approved these changes Mar 1, 2026
@0xSysR3ll
Copy link
Contributor

You forgot to run pnpm format before committing.

Copy link
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

Adds a Jellyfin scanner fallback so items that store TMDB IDs under the legacy TheMovieDb provider key (e.g., written by Shokofin) can still be matched during Seerr library sync.

Changes:

  • Movie scanning: derive tmdbId from ProviderIds.Tmdb with fallback to ProviderIds.TheMovieDb
  • TV scanning: treat ProviderIds.TheMovieDb as a valid TMDB identifier source when loading show metadata

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

Comment on lines +63 to +67
let tmdbId = Number(
metadata.ProviderIds.Tmdb ||
metadata.ProviderIds.TheMovieDb ||
null
);
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

metadata.ProviderIds is typed as { Tmdb?: string; Imdb?: string; Tvdb?: string; AniDB?: string; } (see @server/api/jellyfin), so accessing metadata.ProviderIds.TheMovieDb will fail TypeScript compilation. Add TheMovieDb?: string to the ProviderIds type (or use an index signature / safe accessor) so this fallback is type-safe.

Copilot uses AI. Check for mistakes.
Comment on lines +234 to +240
if (metadata.ProviderIds.Tmdb || metadata.ProviderIds.TheMovieDb) {
try {
tvShow = await this.getTvShow({
tmdbId: Number(metadata.ProviderIds.Tmdb),
tmdbId: Number(
metadata.ProviderIds.Tmdb ||
metadata.ProviderIds.TheMovieDb
),
Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

Same typing issue here: metadata.ProviderIds.TheMovieDb is not part of the JellyfinLibraryItemExtended.ProviderIds interface, so this will not type-check. Update the Jellyfin ProviderIds type to include TheMovieDb?: string (or otherwise access it safely) to keep the scanner compiling.

Copilot uses AI. Check for mistakes.
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