Skip to content

fix(scanners): decline orphaned requests when media is removed from servarr#3191

Merged
fallenbagel merged 2 commits into
developfrom
fix/handle-orphaned-requests-of-orphaned-media
Jul 3, 2026
Merged

fix(scanners): decline orphaned requests when media is removed from servarr#3191
fallenbagel merged 2 commits into
developfrom
fix/handle-orphaned-requests-of-orphaned-media

Conversation

@fallenbagel

@fallenbagel fallenbagel commented Jun 22, 2026

Copy link
Copy Markdown
Member

Description

This fixes a stuck state where a movie/show shows a Request button but blocks the request as a duplicate.

When an approved request is sent to Radarr/Sonarr and the entry later disappears before completion (manual removal, DB rebuild, list cleanup), the orphan cleanup from #2757 resets the media to UNKNOWN but doesn't touch the request. The request stays APPROVED, so the duplicate-request guard keeps blocking re-requests while the media page renders as un-requested and the user can neither see it as requested nor request it again.

Cleanup now declines the approved requests bound to the orphaned media. DECLINED is the correct terminal state here (the request's fulfilment was abandoned) and it's the one status that clears the duplicate guard, so the user can simply request again. The decline runs through the normal request path, so the standard MEDIA_DECLINED notification fires, which is still appropriate here, since removing an in-flight item from the servarr is an implicit cancellation.

This PR also adds an empty-scan guard. If a server returns an empty list, orphan cleanup for that profile type is skipped. A servarr mid-rebuild serving 200 [] would otherwise look like "every movie was deleted" and mass-orphan (and now mass-decline) the whole library. Genuinely-deleted items are still cleaned up on the next scan once the servarr is populated again.

Orphan cleanup no longer treats an empty servarr response as "everything deleted." Existing tests that encoded deletion as an empty list were updated to use a populated scan missing the target instead.

How Has This Been Tested?

(Only via unit tests)

Screenshots / Logs (if applicable)

Checklist:

  • I have read and followed the contribution guidelines.
  • Disclosed any use of AI (see our policy) (for unit tests)
  • 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

  • New Features

    • Automatically decline approved media requests for orphaned movies and TV shows when they are no longer found on the scanner service, including both standard and 4K variants.
  • Tests

    • Added comprehensive test coverage for orphaned request handling across scanner types.

…ervarr

When an approved request's media was removed from Radarr/Sonarr before completion, the orphan
cleanup reset the media to UNKNOWN but left the request APPROVED, leaving it stuck due to the
duplicate guard block while UI showed it as un-requested. Decline the matching approved requests
during cleanup so the guard clears and the user can request it again. Also skips orphan cleanup when
the server returns an empty list, so a servarr related issues can't mass-orphan an entire library.
@fallenbagel fallenbagel requested a review from Copilot June 22, 2026 18:51
@fallenbagel fallenbagel requested a review from a team as a code owner June 22, 2026 18:51
@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a declineOrphanedRequests protected method to BaseScanner that marks approved MediaRequest records as DECLINED when their associated media is orphaned. Both RadarrScanner and SonarrScanner integrate this method into orphan cleanup, also adding empty-server flags to skip cleanup when a server returns no results. Tests are updated and expanded accordingly.

Changes

Orphaned Request Decline Flow

Layer / File(s) Summary
BaseScanner.declineOrphanedRequests method
server/lib/scanners/baseScanner.ts
Expands imports to include MediaRequestStatus and MediaRequest, and adds a protected method that enforces media.requests is loaded, filters by is4k + APPROVED status, sets each to DECLINED, populates request.media for notification hooks, saves, and logs per request.
Radarr scanner: empty-server guard and orphan request decline
server/lib/scanners/radarr/index.ts
Adds serverReturnedEmpty/server4kReturnedEmpty flags reset each run; sets them with a warning when getMovies() returns empty and suppresses cleanup accordingly; eager-loads requests relations and calls declineOrphanedRequests after resetting orphaned movie status to UNKNOWN.
Sonarr scanner: empty-server guard and orphan request decline
server/lib/scanners/sonarr/index.ts
Mirrors the Radarr pattern for series: adds empty-server flags, suppresses cleanup when empty, eager-loads both seasons and requests, and calls declineOrphanedRequests per dimension in cleanupOrphanedShows.
Test suite updates and new orphaned request handling tests
server/lib/scanners/radarr/radarr.test.ts, server/lib/scanners/sonarr/sonarr.test.ts
Updates existing cleanup stubs from empty-list to mismatching-id returns, mocks MediaRequest.sendNotification, and adds new orphaned request handling suites covering: decline + UNKNOWN reset when orphaned, no-decline when media exists or server returns empty, throw when requests relation is unloaded, and selective decline of only the matching 4k/standard dimension.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • seerr-team/seerr#2757: Both PRs modify the Radarr/Sonarr orphan-cleanup flow to reset "processing" media to UNKNOWN; this PR extends that same cleanup path by calling declineOrphanedRequests to additionally mark orphaned approved requests as DECLINED.

Suggested reviewers

  • gauthier-th
  • 0xSysR3ll

Poem

🐇 Hop hop, the orphans are found,
Their requests now DECLINED, safe and sound.
Empty servers? We'll skip the sweep,
No phantom declines while scanners sleep.
The rabbit watches, relations in hand—
Only loaded requests get scanned! 🌿

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title accurately describes the main change: declining orphaned requests when media is removed from servarr, which is the core fix addressed across all scanner implementations.

✏️ 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 Fix/handle orphaned requests of orphaned media fix(scanners): decline orphaned requests when media is removed from servarr Jun 22, 2026
@fallenbagel fallenbagel changed the title fix(scanners): decline orphaned requests when media is removed from servarr fix: decline orphaned requests when media is removed from servarr Jun 22, 2026
@fallenbagel fallenbagel changed the title fix: decline orphaned requests when media is removed from servarr fix: decline orphaned requests when media is removed from servarr Jun 22, 2026
@fallenbagel fallenbagel changed the title fix: decline orphaned requests when media is removed from servarr fix(scanners): decline orphaned requests when media is removed from servarr Jun 22, 2026

Copilot AI 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.

Pull request overview

This PR addresses a stuck “duplicate request” state by ensuring that when Sonarr/Radarr orphan cleanup resets orphaned in-flight media back to UNKNOWN, any associated APPROVED requests are also transitioned to DECLINED so users can re-request the media. It also adds a safety guard to skip orphan cleanup for a profile type when a Servarr server returns an empty library list, preventing accidental mass-orphan/mass-decline during rebuilds.

Changes:

  • Decline APPROVED requests for media determined to be orphaned during Radarr/Sonarr orphan cleanup.
  • Add “empty scan” detection to skip orphan cleanup for that profile type when a server returns 200 [].
  • Update/add unit tests for Radarr and Sonarr scanners to reflect the new cleanup behavior and the empty-scan guard.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
server/lib/scanners/baseScanner.ts Adds shared helper to decline orphaned approved requests during scanner cleanup.
server/lib/scanners/radarr/index.ts Adds empty-scan guard and declines orphaned requests during Radarr orphan cleanup.
server/lib/scanners/sonarr/index.ts Adds empty-scan guard and declines orphaned requests during Sonarr orphan cleanup.
server/lib/scanners/radarr/radarr.test.ts Updates existing tests and adds coverage for orphaned request handling + empty-scan guard.
server/lib/scanners/sonarr/sonarr.test.ts Updates existing tests and adds coverage for orphaned request handling + empty-scan guard.

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

Comment thread server/lib/scanners/baseScanner.ts

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

LGTM

@seerr-automation-bot seerr-automation-bot added this to the v3.4.0 milestone Jun 24, 2026
@fallenbagel fallenbagel enabled auto-merge (squash) June 24, 2026 12:26
Comment thread server/lib/scanners/radarr/index.ts
@fallenbagel fallenbagel merged commit 2e0e4ce into develop Jul 3, 2026
23 of 26 checks passed
@fallenbagel fallenbagel deleted the fix/handle-orphaned-requests-of-orphaned-media branch July 3, 2026 13:39
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.

5 participants