Skip to content

fix: handle already-removed media in radarr/sonarr delete#3209

Open
fallenbagel wants to merge 7 commits into
developfrom
fix/delete-media-already-removed-in-arr
Open

fix: handle already-removed media in radarr/sonarr delete#3209
fallenbagel wants to merge 7 commits into
developfrom
fix/delete-media-already-removed-in-arr

Conversation

@fallenbagel

@fallenbagel fallenbagel commented Jun 28, 2026

Copy link
Copy Markdown
Member

Description

The delete chain in ManageSlideOver runs two sequential awaits with no error handling, so a rejected first request meant the record was never cleaned up and the slideover never closed.

removeMovie and removeSeries now short-circuit when the item is no longer in the *arr library and swallow a 404 on the delete itself to handle the race where the item is removed between lookup and delete. Real errors (like network, auth) are re-thrown unchanged. The /file route catch is updated to return 500 on genuine failures instead of a flat 404, and EntityNotFoundError is surfaced as 404 explicitly.

Also fixes a hanging request in the /file handler when no default *arr is configured. The bare return was never sending a response. Now returns 204.

How Has This Been Tested?

  • Have not tested manually but via unit test only.

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
    • Media file deletion now returns 204 when service settings are missing, 404 when the media entity isn’t found, and 500 with a consistent failure message for other errors.
    • Radarr/Sonarr “remove” actions now safely no-op when the item/series isn’t in the library; 404 delete failures are ignored while other errors still fail.
    • Lookup failures preserve the original status (e.g., 401) and empty lookups return “not found”.
  • New Features
    • ManageSlideOver now shows toast notifications when removing media files fails.
  • Tests
    • Expanded coverage for Radarr/Sonarr lookup and remove success/error paths.

@fallenbagel
fallenbagel requested a review from Copilot June 28, 2026 20:31
@fallenbagel
fallenbagel requested a review from a team as a code owner June 28, 2026 20:31
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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

Fixes Radarr and Sonarr deletion handling for missing items and 404 responses, makes the media delete route return explicit status responses, and adds toast feedback for media deletion failures.

Changes

Servarr and media deletion error handling

Layer / File(s) Summary
Radarr lookup and remove handling
server/api/servarr/radarr.ts, server/api/servarr/radarr.test.ts
Lookup errors are rethrown, empty results report Movie not found, missing library entries skip deletion, and deletion 404s are ignored. Tests cover these paths.
Sonarr lookup and remove handling
server/api/servarr/sonarr.ts, server/api/servarr/sonarr.test.ts
Lookup errors are rethrown, empty results report Series not found, missing library entries skip deletion, and deletion 404s are ignored. Tests cover these paths.
Media file delete route responses
server/routes/media.ts
DELETE /:id/file returns 204 for missing service settings, 404 for missing media, and 500 for other failures.
Media removal error feedback
src/components/ManageSlideOver/index.tsx, src/i18n/locale/en.json
Media deletion failures display an error toast with localized text and trigger revalidation without closing the slide-over.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • seerr-team/seerr#3109: Modifies the same media delete route’s missing-service and error-handling behavior.

Suggested reviewers: copilot, m0nsterrr, gauthier-th, 0xsysr3ll

Poem

A bunny watched the errors flee,
“Four-oh-four is fine,” said she.
Toasts now sparkle, routes reply,
Lost files softly say goodbye. 🐇

🚥 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 is concise and accurately describes the main change: handling already-removed media during Radarr/Sonarr deletion.
Linked Issues check ✅ Passed The PR implements the Radarr/Sonarr deletion fallback, treats 404 delete responses as non-fatal, and preserves other failures while completing cleanup and UI flow.
Out of Scope Changes check ✅ Passed The route, UI, toast, and translation changes support the deletion-handling fix and do not introduce unrelated scope.

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.

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 improves robustness of media deletion flows by making Radarr/Sonarr deletions tolerant to already-removed items, fixing a no-response path in the /media/:id/file route, and refining error handling to distinguish “not found” from genuine failures.

Changes:

  • Make RadarrAPI.removeMovie / SonarrAPI.removeSeries no-op when the item is not present and treat a 404 on the delete request as success.
  • Fix /api/v1/media/:id/file returning no response when no default *arr service is configured (now returns 204).
  • Update /api/v1/media/:id/file error handling to return 404 for EntityNotFoundError and 500 for real failures.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
server/routes/media.ts Fixes hanging /file request path and refines error mapping for delete-file route.
server/api/servarr/sonarr.ts Makes series removal tolerant of already-removed series (ignore 404).
server/api/servarr/sonarr.test.ts Adds unit tests covering removeSeries behavior for present/missing/404/error cases.
server/api/servarr/radarr.ts Makes movie removal tolerant of already-removed movies (ignore 404).
server/api/servarr/radarr.test.ts Adds unit tests covering removeMovie behavior for present/missing/404/error cases.

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

Comment thread server/routes/media.ts
Comment thread server/api/servarr/radarr.ts
Comment thread server/api/servarr/sonarr.ts

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

Actionable comments posted: 2

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

Inline comments:
In `@server/api/servarr/radarr.ts`:
- Around line 270-272: The lookup path in removeMovie is still swallowing real
Radarr errors because getMovieByTmdbId() rethrows everything as “Movie not
found” inside the broad try. Update removeMovie and/or getMovieByTmdbId() so
only a genuine missing-movie case becomes that message, while
auth/network/transport failures from the lookup are rethrown unchanged; use the
removeMovie and getMovieByTmdbId symbols to keep the lookup branch separate from
the DELETE handling.

In `@server/api/servarr/sonarr.ts`:
- Around line 413-415: The lookup path in removeSeries is still swallowing
non-404 failures because getSeriesByTvdbId() throws a generic "Series not found"
inside the broad try/catch. Update removeSeries and/or getSeriesByTvdbId so only
true not-found cases are mapped to that error, while Sonarr
auth/network/transport errors from the lookup are rethrown unchanged. Use the
existing removeSeries and getSeriesByTvdbId methods to isolate the
DELETE-specific handling from the series lookup path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4b541d82-3885-44a3-902e-70b18f572ade

📥 Commits

Reviewing files that changed from the base of the PR and between ebac489 and 54cce36.

📒 Files selected for processing (5)
  • server/api/servarr/radarr.test.ts
  • server/api/servarr/radarr.ts
  • server/api/servarr/sonarr.test.ts
  • server/api/servarr/sonarr.ts
  • server/routes/media.ts

Comment thread server/api/servarr/radarr.ts Outdated
Comment thread server/api/servarr/sonarr.ts Outdated
When a movie is absent from the *arr library, removeMovie/removeSeries now returns instead of
throwing, so the Seerr record can still be cleaned up.

fix #3112
@fallenbagel
fallenbagel force-pushed the fix/delete-media-already-removed-in-arr branch from 54cce36 to 78f24ee Compare June 28, 2026 20:54

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

Actionable comments posted: 1

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

Inline comments:
In `@server/routes/media.ts`:
- Around line 290-294: The delete-media error logging in the media route is
writing upstream error text directly via e.message, which can contain control
characters. Update the logger.error call in the media delete handler to sanitize
the message before logging by stripping CR/LF and other control characters from
the error text, while keeping the existing context fields like label and mediaId
intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c3aacc35-1896-4f0f-a6f0-f78908d5e81f

📥 Commits

Reviewing files that changed from the base of the PR and between 54cce36 and 78f24ee.

📒 Files selected for processing (5)
  • server/api/servarr/radarr.test.ts
  • server/api/servarr/radarr.ts
  • server/api/servarr/sonarr.test.ts
  • server/api/servarr/sonarr.ts
  • server/routes/media.ts

Comment thread server/routes/media.ts
@seerr-automation-bot seerr-automation-bot added this to the v3.4.0 milestone Jun 29, 2026
Comment thread server/routes/media.ts
gauthier-th
gauthier-th previously approved these changes Jul 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

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

Comment thread server/api/servarr/radarr.ts
Comment thread server/api/servarr/sonarr.ts
M0NsTeRRR
M0NsTeRRR previously approved these changes Jul 22, 2026
Copilot AI review requested due to automatic review settings July 22, 2026 23:58
@github-actions github-actions Bot added the i18n-out-of-sync User forgot to run pnpm i18n:extract label Jul 22, 2026
@github-actions

Copy link
Copy Markdown

The i18n check failed because translation messages are out of sync.

This usually happens when you've added or modified translation strings in your code but haven't updated the translation file.

Please run pnpm i18n:extract and commit the changes.

@fallenbagel
fallenbagel requested a review from M0NsTeRRR July 22, 2026 23:59
@github-actions github-actions Bot removed the i18n-out-of-sync User forgot to run pnpm i18n:extract label Jul 23, 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

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

Comment on lines +155 to +159
} catch {
addToast(intl.formatMessage(messages.removemediaerror), {
appearance: 'error',
autoDismiss: true,
});
Comment thread server/api/servarr/sonarr.ts Outdated
Comment on lines +415 to +417
public removeSeries = async (serieId: number): Promise<void> => {
const { id, title } = await this.getSeriesByTvdbId(serieId);

Copilot AI review requested due to automatic review settings July 23, 2026 00:02

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

Copilot reviewed 7 out of 7 changed files in this pull request and generated no new comments.

Copilot AI review requested due to automatic review settings July 23, 2026 00:23

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

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

Comment thread server/routes/media.ts
Comment on lines 245 to 255
if (!serviceSettings) {
logger.warn(
`There is no default ${
is4k ? '4K ' : '' + isMovie ? 'Radarr' : 'Sonarr'
}/ server configured. Did you set any of your ${
is4k ? '4K ' : '' + isMovie ? 'Radarr' : 'Sonarr'
} servers as default?`,
const arrName = `${is4k ? '4K ' : ''}${isMovie ? 'Radarr' : 'Sonarr'}`;
logger.info(
`There is no default ${arrName} server configured. Did you set any of your ${arrName} servers as default?`,
{
label: 'Media Request',
mediaId: media.id,
}
);
return;
return res.status(204).send();
}
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.

Exception when deleting already deleted file from Radarr

5 participants