Deletion Safety
Lifecycle rules can delete media. This page explains, in plain language, every check that stands between a rule firing and a file being removed. If you’re worried about handing your library over to an automated tool, read this end-to-end.
What we’re trying to prevent
Section titled “What we’re trying to prevent”The single concrete failure mode that this entire system is designed to make impossible:
You create or edit a rule, intending it to match a small number of items, and the system instead matches every item in your library and queues all of it for deletion.
Every check below exists because of a specific way that scenario could happen — a typo in a rule, a misconfigured action, a metadata change in your *arr instance, an item you forgot you’d added. None of these can, on their own, cause unintended data loss. The system has to be wrong in four independent places simultaneously for an item to be deleted by accident.
The four-layer model
Section titled “The four-layer model”| Layer | When it happens | What it stops |
|---|---|---|
| 1. When you save | While you’re building or editing a rule | Saving a destructive rule without a recycle bin or explicit acknowledgement |
| 2. When matches are detected | When the engine looks for items to act on | An empty, broken, or all-disabled rule from matching the entire library |
| 3. After matches are found | Before any action is queued | Stale or excluded items getting queued for deletion |
| 4. When the action runs | The moment before each individual deletion | Acting on the wrong item due to renames or metadata drift |
The rest of this page walks through each layer in user terms.
Layer 1 — When you save
Section titled “Layer 1 — When you save”Before a rule even runs, the rule editor has several built-in checks.
Preview before you save
Section titled “Preview before you save”Every rule has a Preview panel. As you build the rule, it shows you exactly which items match — using the same engine that the real lifecycle process uses, so what you see in preview is what will happen for real.
If the preview shows more items than you expected, stop and adjust the rule. Don’t save yet.
“Enable lifecycle action” is a separate switch
Section titled ““Enable lifecycle action” is a separate switch”Rule sets have two different toggles:
- Enabled — turns detection on or off. When off, the rule set is not evaluated and its pending actions are cancelled.
- Enable lifecycle action — when off, matches are still detected and shown to you, but no deletions are ever scheduled, no matter how the rules are configured. Turning it off cancels the rule set’s pending actions straight away.
This means you can build a rule, save it, watch which items it matches over a few detection cycles, and only then arm it by turning Enable lifecycle action on.
Recycle bin requirement for destructive actions
Section titled “Recycle bin requirement for destructive actions”When you pick an action type whose name contains “Delete” — that’s “Delete from Radarr/Sonarr/Lidarr”, “Delete Files Only”, “Unmonitor & Delete Files”, and “Monitor & Delete Files” — Librariarr checks the *arr instance you’re targeting to see whether it has a Recycle Bin Path configured.
- If the recycle bin is set up: deleted files go there first. *arr keeps them for its configured cleanup retention period (typically 7 days, configurable), so you have a recovery window if anything goes wrong.
- If the recycle bin is missing: deletions are immediate and permanent.
If the recycle bin is missing, you cannot save the rule silently. The save flow:
- Shows an inline amber warning under the action type dropdown: “Recycle bin is disabled on this Sonarr/Radarr/Lidarr instance. Deletes will be permanent.”
- Pops up a confirmation dialog you have to read and tick: “I understand that deletes will be permanent and unrecoverable.”
- Provides a direct link to the *arr instance’s Media Management settings so you can configure a recycle bin without losing your work in progress.
The acknowledgement is remembered per *arr instance for the duration of your session — once you’ve ticked through it for that instance, you won’t be re-prompted on the next save.
Malformed rules are rejected before saving
Section titled “Malformed rules are rejected before saving”The structural validator that runs on every save guarantees:
- Each rule has both a
fieldand anoperator, both as strings. - Each rule group has a
conditionof"AND"or"OR"and an array of rules. - Stream-query groups declare a valid
streamType(audio,video, orsubtitle). - The serialized rule set is at most 50 KB and at most 100 top-level rules.
- No rule uses a field that can never have a value for the rule set’s library type (for example a Sonarr season count on a movie rule set, or any Seerr field on a music rule set).
- The action belongs to the right *arr family for the library type, its *arr instance exists, and a Change Quality Profile action names a target profile.
A rule set that fails any of these checks is rejected with an HTTP 400 error and never reaches the database.
The validator does not check that operator names, or field names it has never heard of, are recognized by the engine — a rule with a typo’d operator like "equlas" will be saved successfully. That class of error is caught later, by the engine’s safety net at detection time (see Check 3 below).
Layer 2 — When matches are detected
Section titled “Layer 2 — When matches are detected”This is the most important layer. When the scheduler runs (or when you click Run Now), the engine has to figure out which items match the rule. A bug here would be the most dangerous, so the engine has three independent checks that all have to pass.
Check 1 — Empty or all-disabled rules can’t match anything
Section titled “Check 1 — Empty or all-disabled rules can’t match anything”Before the engine touches your library, it checks whether the rule actually has at least one enabled rule somewhere inside it. If the rule is empty, or every group is disabled, or every individual rule is disabled, the engine returns an empty list immediately. No database query runs. No matches are recorded. No actions are scheduled.
This means it’s impossible for a “blank” rule (one you’ve turned off, or accidentally cleared, or never finished writing) to match anything.
Check 2 — Rules that depend on external systems can’t accidentally match everything
Section titled “Check 2 — Rules that depend on external systems can’t accidentally match everything”Some rule fields can be checked directly in your library database — things like resolution, file size, year, play count. The engine handles these fast.
Other rule fields need information from outside the database — for example, whether *arr considers an item “monitored”, or whether someone requested it via Seerr, or whether a wildcard pattern matches a stream language. The engine can’t translate those into a database query, so it has to fetch a list of candidates first and then check each one in memory.
The danger here is subtle: a rule the engine can’t translate into a database query contributes no constraint to that query, so on its own the query could return your whole library. The engine marks every such rule as “must be checked in memory” and carries that marker through the rule’s AND/OR logic, so the database query is always at least as broad as the final answer and the in-memory pass always narrows it. There is no path where an outside-system rule lets your whole library through.
There’s a related trap on the outside-system side itself: fields like Found In Arr (foundInArr) and Has Request (seerrRequested) describe an item’s absence from the external system, so if that data simply isn’t there — you disabled your only Radarr instance, or never connected Seerr — “not found in *arr” would be true for everything.
Detection therefore refuses to evaluate a rule set whose *arr or Seerr fields have no enabled instance behind them. The rule set is skipped with a warning in System Logs, its existing matches are left untouched, and previews return an error rather than a whole-library match list. An unreachable instance is skipped for that cycle for the same reason — and so is a Seerr request list that can’t be read in full, since every request it missed would read as “never requested”. Manually executing or retrying the actions of a music rule set with Seerr criteria is refused too. Seerr fields are rejected outright on music rule sets, where Seerr data can never exist; a music rule set that already carries them is disarmed — matches cleared, pending actions cancelled.
A rule set can also be skipped for its own rules. A criterion whose value belongs to one episode or one track can never make a whole show or artist the target of an action. With Match against entire series or Match against entire artist on, a rule judges a whole show or artist and its action covers all of it, so criteria that describe one episode or track — Resolution, the codecs, Year, Genre, Content Rating, Studio, a stream query and the like, everything Librariarr stores per episode or track — can’t be used there: one 4K episode would otherwise make a whole show match, and Delete from Sonarr take every other episode with it. Matched By Rule Set, Has Pending Action and Server Count, which each episode or track also has its own of, can be used there, but a show or artist then matches only when the rule holds for every one of its episodes or tracks — Matched By Rule Set = X never selects a show X matched one episode of (see Cross-system criteria in series and artist scope). With the scope off they are checked per episode, but an action that acts on the whole show or artist anyway — Delete from Sonarr or Lidarr, Change Quality Profile, Unmonitor & Delete Files, Monitor & Delete Files, Lidarr’s Unmonitor Only, Search for New Copy and Search after, and Arr tags — can’t follow them (nor, there, an episode’s own play count or last play). Saving either is refused, and Preview, Test Media and the Match Changes Preview refuse it too, judging the editor’s unsaved scope and action as a save would. One saved before that rule, or restored from a backup, is skipped by detection with the reason (its matches are kept), Preview and Test Media answer with the reason, and its pending actions are held — not run on schedule, by Execute, Execute All, Retry or the API — until it is edited; so is a pending action whose own action is such a one. See Criteria not allowed with series scope on and Actions on the whole show with series scope off.
Play history is the third outside dependency, and it fails the same way. Until a server’s watch history has been synced, every item on it looks never watched, so Play Count = 0 or Last Played more than 180 days ago would match the whole library. A rule set that reads play activity — Watched By User, Play Count, Last Played, and the series rollups built on them — is therefore skipped while any server it targets has no established play history: it has never completed a watch-history sync, its history was just cleared (a purge, a restore, a change of watch-history source), or a Tracearr import is still backfilling. Previews return an error naming the server, and the rule editor shows a “Play history not established yet” warning.
The same refusal applies to ad-hoc Query page actions: running an action on results whose Arr/Seerr criteria couldn’t actually be evaluated (no Arr server selected for the action’s media type, a disabled one, no enabled Seerr instance, or Seerr criteria on music), or whose play-activity criteria read a server with no known watch history, is blocked with an explanatory error before anything runs. So is an action on a whole show or artist (Delete from Sonarr or Lidarr, Change Quality Profile, tags, …) on results of a query whose criteria describe one episode or track — the same criteria a rule set with the scope off can’t follow under that action; the file deletes, which act on the matched episodes or tracks, stay available. See When a query action is refused.
Check 3 — A final safety net for unrecognized rules
Section titled “Check 3 — A final safety net for unrecognized rules”Even if checks 1 and 2 had a bug, there’s a third check at the bottom of the engine. After translating every rule, it asks itself: “Did all of these rules produce nothing the database can act on, and is there no in-memory follow-up planned?”
If the answer is yes, it returns an empty list and stops. The library is not queried. This is the explicit guard against:
- A rule that accidentally references a field name with a typo.
- A rule that uses an operator the engine doesn’t recognize.
- A rule that, because of some future change to the codebase, can’t be evaluated at all.
In all of these cases, the engine refuses to match anything rather than risk matching everything. The block is marked with a code comment so anyone editing the engine knows it’s load-bearing, and the integration test suite that runs the full lifecycle pipeline against a real database would fail if it were broken.
When the in-memory pass also runs
Section titled “When the in-memory pass also runs”Some rule sets have an additional in-memory verification pass after the database query. It runs whenever the rule set contains any of: a wildcard pattern (* or ?), an Arr-dependent field, a Seerr-dependent field, a cross-system field, a stream-count field, a stream-query computed field, a resolution rule, a list field (genre, label or country), or a series-aggregate field. In those cases, every candidate the database returns is re-checked against every rule in memory before being marked as a match.
For rule sets that only use simple database-expressible fields (resolution, year, file size, dates, play count, etc.), the database query alone is the final answer — there is no second pass, because the database has already enforced every condition exactly. Defenses 1–3 above are what guarantees this is safe.
Layer 3 — After matches are found, before actions are queued
Section titled “Layer 3 — After matches are found, before actions are queued”Once the engine has identified which items match a rule, those matches don’t immediately turn into deletions. Several things happen between “this item matched” and “an action is scheduled”:
A cooling-off period before any deletion runs
Section titled “A cooling-off period before any deletion runs”Every rule set has a Delay (days) setting. When a match becomes a pending action, it’s scheduled to run that many days in the future, not immediately. The default is 7 days, and we strongly recommend keeping that or longer.
The delay gives you time to:
- Open the Pending Actions page and see what’s queued up.
- Add items you want to keep to the Lifecycle Exceptions list.
- Disable or edit the rule if it matched things it shouldn’t have.
- Receive a Discord notification (if you’ve turned on Send Discord notification on match changes) when items enter or leave the match list.
Setting the delay to 0 disables this safety window entirely. Don’t do that until you’ve run the rule for at least one full cycle with a delay and verified it’s matching what you expect.
Stale matches are cancelled automatically (unless you opt out)
Section titled “Stale matches are cancelled automatically (unless you opt out)”By default, the scheduler checks on every detection run whether previously-matched items still match. If they don’t (because the rule changed, the item’s metadata changed, or the item is no longer in your library), the match is removed and any pending action queued for it is cancelled before it runs. You won’t get a deletion for an item that has stopped being a match by the time the delay expires.
This auto-cleanup is the default and is the safer choice for almost everyone.
The “Sticky matches” toggle
Section titled “The “Sticky matches” toggle”Each rule set has a Sticky matches toggle. When you turn it on, the auto-cleanup described above is disabled:
- Items that previously matched stay in the match list even if they no longer meet the rule’s criteria.
- Their pending actions are not cancelled — they will execute when the delay expires.
- The only way to remove a stale match is to click Re-evaluate in the Rule Matches view manually.
The trade-off is intentional. With sticky off (the default), a brief change in your library — a play count incrementing, a metadata refresh in *arr, a temporary file size change — can pull an item out of a rule’s match list and protect it from deletion automatically. With sticky on, you get a stronger guarantee that “once an item matches, it gets actioned”, at the cost of giving up that automatic protection.
Editing a rule re-checks its matches
Section titled “Editing a rule re-checks its matches”When you change a rule’s conditions, its matches are re-checked against the new rules — at once with Save and re-detect, or on the next scheduled detection run with Save only (see the caution in Layer 1), and the rule set’s pending actions wait for that re-check. Items the edited rule no longer selects lose their match and their pending action, unless Sticky matches is on, in which case only Re-evaluate on the Rule Matches page drops them. Changing the delay asks whether to reschedule the actions already pending to the new delay from today. Switching the *arr server of a rule set that uses *arr criteria wipes its matches and pending actions outright, so nothing judged against the old instance survives.
Lifecycle Exceptions are honored at every step
Section titled “Lifecycle Exceptions are honored at every step”Any item you’ve added to your Lifecycle Exceptions list:
- Is excluded from new matches when detection runs.
- Has any existing pending action on it cancelled before execution.
- Is logged when it’s skipped, so you can see in System Logs that the protection worked.
An exception covers the item on every server. When the same movie, episode or track exists on more than one of your servers (or in more than one library), Librariarr treats them as one title — the one record in Radarr, Sonarr or Lidarr that every copy is backed by — so excluding it from any copy protects them all. On the Rule Matches page a title found on several servers appears as a single row with a chip per server; excluding that row excludes the title everywhere, and a pending action on another copy is cancelled too. Excluding a title also takes every copy of it out of the rule set’s Plex collection straight away, each on its own server — you don’t have to wait for the next detection run. This holds for series, season, artist and album exclusions as well as single items, and a series exclusion reaches the show on every server even when the servers title it differently.
A title that stays matched keeps its place in the queue. If the copy Librariarr kept stops matching (say it was played on its own server) while a copy on another server still matches, the match and its pending action move to that copy with the same scheduled date — the countdown does not restart, and a sticky rule set does not end up with two actions against the one record.
For series rules that target individual episodes, the system tracks each episode separately. If you’ve excepted some episodes of a show but not others, only the non-excepted ones can be acted on. If you’ve excepted every targeted episode of a show, the entire action is cancelled.
Whole-record actions get an extra check. Delete from Sonarr / Delete from Lidarr remove the entire series or artist — including episodes or tracks the rule never matched. Because a “surgical” exclusion is impossible for those, the action is refused outright when any episode of the series (or track of the artist) is on the exception list, even one that isn’t part of the current match. This applies to scheduled execution, the manual Execute button, retries of failed actions, and ad-hoc Query-page actions alike, and every refusal is logged.
The series is identified the same way it is everywhere else in Librariarr — by its TVDB/TMDB identity, not by its title. So an exception you placed on a copy of the show on one server still protects it when the action targets the copy on another, even if the two servers name the show differently (“The Office” and “The Office (US)”); and an exception on one show does not block a delete of a different show that happens to share its title. Artists are matched by name and by their MusicBrainz artist id, the id Lidarr deletes an artist by: an exception protects the artist under any spelling of its name that carries the same id, and every artist sharing its name. Two different bands called “Nirvana” therefore protect each other — the library cannot always tell two artists from one artist listed under two ids, and a skipped delete is the safe mistake.
Layer 4 — When the action runs
Section titled “Layer 4 — When the action runs”Even after all the previous layers approve, there are still checks the moment before each individual deletion happens.
One last check that the item still matches
Section titled “One last check that the item still matches”Stale-match cancellation actually happens in two places, both as belt-and-braces protection:
-
Right after detection runs: when matches are produced, the scheduler walks through any pending actions for the rule set and deletes any whose item is no longer in the current match set. This is what catches items that dropped out of the match list because of a metadata change.
-
Right before each action executes: just before the deletion is sent to *arr, the system re-checks whether the item is still in the rule’s match list (and whether the item still exists at all). If the answer is no on either count, the action is deleted instead of executed, with a “no longer a match” entry in System Logs.
Together these mean an item has to be a current match at both scheduling time and execution time for the action to actually run.
The item must still be the one that matched
Section titled “The item must still be the one that matched”A match remembers an item, and your media server can change what that item is. A Plex Fix Match or a Jellyfin/Emby Identify rewrites the same library entry to a different title, with different TMDB/TVDB ids, and the next sync records that before the next detection run notices the match is stale. Acting on the match then would reach the new title in Radarr or Sonarr — one your rules never matched — and the title check below would pass, because it compares against the new title.
So before anything runs, Librariarr compares the item with what it looked like when the rule matched it, and refuses it if:
- the title changed. For a series or artist action, that is the name of the show or artist — the action covers the whole show or artist, so renaming one episode or track doesn’t count. For a track-by-track music rule, both the track and its artist must still match. Cosmetic differences (“The Matrix” / “Matrix, The”) are ignored, as in title validation below.
- the TMDB, TVDB or MusicBrainz ID changed — the item now points at a different record in *arr, even if the name is the same.
- a movie’s year moved by more than one. Titles can’t tell remakes apart (“Dune” 1984 and “Dune” 2021), so a Fix Match to a remake is caught by its year even when no ID was recorded.
Scheduled runs, and Retry on a failed action, compare with what the action recorded when it was scheduled; a scheduled run cancels that one action. The cancellation is logged in System Logs with the reason (“item identity changed since scheduling”), and the item’s match is cleared along with the action, since it described the old title too. The next detection run then evaluates the item as it is now, even on a rule set with Sticky matches on: if the new title matches the rule, it is matched and scheduled afresh with a full delay, so you can review it on the Pending Actions page first; if it doesn’t, it drops out.
The Execute button on the Pending page, and the public API, compare with the match as the last detection run stored it. They refuse the whole request and ask you to run detection again, which re-checks the item against your rules as it is now. Every match records the ID along with the title; a match recorded by an older version gains it the next time the item matches.
Title validation against *arr
Section titled “Title validation against *arr”This is a subtle but important protection. Imagine you have a rule that’s about to delete a movie called “The Matrix”. In between when the action was scheduled and when it runs, your library refreshes and the *arr record for that TMDB ID has been renamed (because the metadata source corrected itself, or because you manually renamed it). The system now has a TMDB ID pointing at one title in your library and a different title in *arr.
To prevent acting on the wrong record, Librariarr compares both titles before sending the delete to *arr. The comparison normalizes for:
- Case (“The Matrix” / “the matrix”)
- Article placement (“The Matrix” / “Matrix, The”)
- Year suffixes in parentheses (“Avatar (2009)” / “Avatar”)
- Punctuation and ampersands (“Fish & Chips” / “Fish and Chips”)
- Whitespace differences
After normalization, if the titles match exactly, the action proceeds. If they don’t, there’s a partial-match fallback that allows things like “Agents of SHIELD” / “Marvel’s Agents of SHIELD” through — but only when both titles are at least 4 characters and the shorter is at least 50% the length of the longer (so short-title collisions like “It” / “It Follows” are still blocked).
There’s also a year guard that runs first, because title normalization strips the very parentheticals that tell remakes apart (“Dune (1984)” and “Dune (2021)” both normalize to “dune”). For movies, the *arr year and the library year describe the same release, so they must match within a year — a wider gap means the external ID points at a different work and the action is refused. For series the comparison is one-directional: an episode is stored with its own air year, while *arr returns the series’ premiere year, so an episode legitimately airs years after the show premiered. Only the reverse is impossible — a correct series can’t have premiered well after the episode aired — so the guard rejects only when the resolved series premiered more than a year later than the episode (which means the ID resolved to a newer same-named series).
If neither check passes, the action is rejected with an error logged to System Logs and surfaced in the Pending Actions page. The action moves to “Failed” status — it does not execute against the unverified record.
When you retry a failed action manually from the Pending Actions page, you have the option to skip title validation if you’ve inspected the mismatch and confirmed it’s safe (for example, a legitimate rename you’ve already verified). A retry still runs every other guard: the rule set must be enabled (a disabled rule set’s matches are frozen, so its failed actions can’t be re-fired), the item must still be a current match, and the exception checks — including the whole-record sibling check — must pass. A retried file delete acts only on the episodes or tracks that still match and have no exception; it is refused when none are left, and a whole-record delete is refused when any of its episodes or tracks has one.
Recoverability depends on *arr’s recycle bin, not on Librariarr
Section titled “Recoverability depends on *arr’s recycle bin, not on Librariarr”There’s a common mental model that’s worth being explicit about: the recycle bin is a *feature of your arr instance, not of Librariarr. When Librariarr tells *arr to delete an item, *arr decides whether to move the file to its configured recycle bin path or to hard-delete it, based on its own settings.
The save-time recycle bin check (Layer 1) is what makes sure you’ve configured the recycle bin in *arr before you arm a destructive rule. Once an action runs, the *arr instance is the only thing protecting you. If the recycle bin was disabled or removed in *arr after you saved the rule, Librariarr will not catch that — *arr will hard-delete and you’ll be relying on filesystem snapshots or backups instead.
This is why the save-time acknowledgement matters and why we recommend treating it as a real check rather than a click-through.
One failure doesn’t cascade into many
Section titled “One failure doesn’t cascade into many”Each individual action runs independently. If one fails — the network blipped, the title check failed, anything — that single failure is recorded with an error message in the Pending Actions page (the action moves to “Failed” status), logged to System Logs, optionally announced via Discord, and does not affect the other actions in the same run. A failed action is never re-run on its own; it sits there until you decide what to do with it.
The one exception is an *arr instance that is down altogether (the connection is refused, or a lookup goes unanswered after its retries). Rather than wait through the same timeout for every item, a scheduled run leaves that instance’s remaining actions pending for the next run, and a manual Execute fails them with the same error without contacting the instance again.
Runs never overlap
Section titled “Runs never overlap”The same item can’t be acted on twice at once. Execute All on a rule set, a per-item Execute, a Retry, and each action of a scheduled run claim what they act on first; a request that overlaps one already running is refused (“already running”), and a scheduled run leaves a claimed action pending for its next pass. A Query-page action and a rule set’s actions never run at the same time, since they can reach the same *arr record through different copies. Before each scheduled action is sent, it is re-read: one that was cancelled, rescheduled, re-configured or protected by a new exception since the run started is left alone.
One action per *arr record
Section titled “One action per *arr record”When a rule set targets several servers, the copies of one title (same TMDB, TVDB or MusicBrainz id) are merged into one match with a chip per server, so one *arr record gets one action, not one per copy. On a music rule set evaluated per track, an artist-level action (such as Delete from Lidarr) is scheduled once per artist rather than once per track. Before Delete from Lidarr removes an artist, Librariarr also asks Lidarr whether any other MusicBrainz id the same artist name carries in your library is the same artist, and refuses if so.
An optional ceiling on each run
Section titled “An optional ceiling on each run”Under Settings → General → Delete without asking, up to N items per run you can cap how many items one run may delete across all rule sets. A run over the limit deletes nothing: its actions stay on the Pending page for you to execute there. It applies to scheduled runs, Execute on the Pending page, and Query-page actions, where it counts the whole run rather than each batch. There is no limit by default. See Limiting how much one run can delete.
Through the API
Section titled “Through the API”Applications you give an API key to (Settings → Authentication → API Keys) can only reach deletion through a key with the Execute lifecycle actions scope, and only in four ways: running a rule set’s action on named matches, queueing an execution run, and removing a lifecycle exception (in bulk or by id). They cannot create or edit rules, run Query-page actions, purge the library, or restore a backup. Everything on this page applies to them, and they are held to stricter limits than you are:
- Every item is named. There is no “execute every match” through the API; leaving the list out, or sending an empty one, is refused.
- At most 25 items per request, and 100 per hour across every key. Removing an exception counts too, because it is what lets the rules match the item again. A request that would go over is refused whole: nothing in it runs.
- Queued runs are held, not trimmed. An execution run queued through the API that would delete more than 25 items, or go over the hourly budget, deletes nothing. The actions stay pending for the rule set’s own schedule or the Pending page, and Discord is told when a webhook is set (at most once every 15 minutes).
Bulk deletion is something only Librariarr itself does: on your schedule, or when you press Execute on the Pending page. See Deletion limits for the details.
What to do if something goes wrong
Section titled “What to do if something goes wrong”If you’ve looked at the Pending Actions page and you don’t like what you see, you have several options. They’re listed least-destructive first.
Option A — Protect specific items (least destructive)
Section titled “Option A — Protect specific items (least destructive)”Add the affected items to Lifecycle Exceptions. There are three ways to do this:
- From the Pending Actions page — find the queued action and use the per-row Add to Exceptions button.
- From the Rule Matches page — find the matched item and use the per-row Add to Exceptions button.
- From the Lifecycle Exceptions page directly — click Add Exception and search for the item.
As soon as you add the exception:
- Any pending action on that item (or another server’s copy of it) is cancelled, and the scheduled run and Execute check the exception list again before acting.
- The item is excluded from future detection, so the rule won’t match it again even if it would otherwise.
- The rule’s match list and all the other pending actions are unaffected.
Use this when only a few items are wrong, or when you want to keep the rule running for the rest of your library.
Option B — Stop deletions for the entire rule set
Section titled “Option B — Stop deletions for the entire rule set”Open the rule set, turn Enable lifecycle action off, click Save. This:
- Cancels every pending action for that rule set immediately.
- Stops new pending actions from being created on the next detection runs.
- Refuses any manual execution of the rule set’s action, including through the public API, until you turn it back on.
- Keeps the match list, so you can still see what the rule selects.
You can turn Enable lifecycle action back on later when you’ve fixed the rule. The next detection run schedules actions for the matches again, each with the full delay.
Use this when you want to halt the entire rule set while you investigate.
Option C — Disable the rule set entirely
Section titled “Option C — Disable the rule set entirely”Same as Option B, but turn Enabled off as well. The rule set is now ignored — no detection, no actions — until you re-enable it. Use this when you want to keep the rule set’s configuration around for later but pause it indefinitely.
Option D — Fix the rule so the unintended items no longer match
Section titled “Option D — Fix the rule so the unintended items no longer match”If you’ve identified a logic error in the rule, edit it and choose Save and re-detect. The Match Changes Preview shows which items the corrected rule drops before you confirm, and confirming re-runs detection: items that no longer match lose their match and their pending action (on a rule set with Sticky matches on, click Re-evaluate on the Rule Matches page as well).
Recovering files that have already been deleted
Section titled “Recovering files that have already been deleted”If a deletion has already run, recovery depends on whether the *arr instance had a recycle bin configured:
- With a recycle bin: the files are in your *arr’s configured recycle bin path, and will stay there until the cleanup retention period elapses (typically 7 days, configurable per *arr instance under Settings → Media Management → File Management). Move them out before then.
- Without a recycle bin: the files were deleted immediately. Recovery is limited to whatever your filesystem provides — snapshots, backups, or other storage-level mechanisms.
This is exactly why the save flow forces the recycle bin acknowledgement (see Layer 1). If you skipped it, you skipped your safety net.
Reporting a safety failure
Section titled “Reporting a safety failure”Every safeguard above is covered by automated tests, and the code is open if you want to verify a claim yourself.
If you find a case where any of them failed, please file an issue at https://github.com/ahembree/librariarr/issues with the rule set’s JSON and a description of what happened. Failures of these guarantees are treated as the highest-priority class of bug.