Slimarr 2.0.0.0 Release Notes
Release date: 2026-09-03
Theme: Discovery & Recommendations, full backend audit, GitHub-reported fixes
Standalone release summary: docs/UPGRADE_NOTES_2.0.0.md
A full backend/frontend audit against the actual implementation (not README
claims), a competitive gap analysis against mature *arr platforms, two
confirmed correctness fixes, and a new deterministic Discovery &
Recommendations feature.
- New: Discovery & Recommendations. Slimarr can now suggest titles
related to what you already own - missing collection entries, sequels/
prequels, and related titles - scored deterministically with a
transparent, human-readable reason for every suggestion. Off by default
(recommendations.enabled: false). Seedocs/RECOMMENDATION_ARCHITECTURE.md. - New: region-specific streaming availability. Looked up per-title via
TMDB's own/watch/providersendpoint only - no streaming service is
scraped or asked for credentials, and availability is timestamped and
treated as stale after 24 hours rather than shown as current indefinitely. - New: explicit hand-off to Radarr/Sonarr from Discovery. Sending a
recommendation to Radarr or Sonarr requires you to confirm the root
folder and quality profile; it's a separate, explicit action, never an
automatic one, and duplicate-checked against the live instance first.
Seerr hand-off is intentionally not implemented this release - see
docs/RECOMMENDATION_INTEGRATIONS.mdfor the capability-detection
rationale. - New: optional, provider-neutral AI reranking abstraction (disabled by
default, no provider shipped enabled). It can only rerank a candidate
list Slimarr already sourced or produce short explanations - it cannot
invent titles or availability, cannot see your Plex token, file paths, or
more watch history than explicitly opted in, and cannot trigger a
download. Every AI-returned ID is re-validated against TMDB before
display. - Fixed:
auto_cleanup_old_orphans()deleted its tracking row before
confirming the underlying file removal actually succeeded, so a failed
cleanup could silently lose track of an orphaned download. It now checks
the removal outcome first and only clears the row on confirmed success. - Fixed: SABnzbd connection-test and job-purge error paths could log an
API key embedded in a request URL inside an exception message. Errors are
now redacted before logging, matching the existing redaction behavior
used elsewhere in the codebase. - Fixed: a storage path containing an embedded
..segment (e.g.
/mnt/local/../nas/movies) could evade NAS-prefix classification,
skipping budget/throttle/cooldown protection entirely. Paths are now
collapsed before classification. - Fixed: on a case-sensitive filesystem (Linux/most Docker/NAS-via-NFS),
path classification lowercased unconditionally, which could cause a false
NAS match or a false miss depending on hownas_path_prefixeswas cased.
Case is now only folded on Windows. - Fixed: if a cross-device NAS copy's final source-file cleanup failed
after the copy itself had already succeeded, the whole move was reported
asfailedeven though the target had a complete, correct copy - leaving
a duplicate and a misleading status. It's now reported as completed with
an explicit warning instead. - Fixed: the image-proxy endpoint could leak a raw exception (including
local filesystem paths) to any client on a cache-fetch failure; it's now
logged server-side only. - Fixed: a job's event timeline had no upper bound, so a job retried
many times returned an ever-growing array fromGET /jobs/{id}. Capped
to the most recent 200 events. - TMDB, Radarr, and Sonarr's original API methods now reuse the app's
pooled HTTP client instead of opening a new connection per call (Radarr/
Sonarr only when the instance's own TLS-verification setting agrees with
the shared client's, so a self-signed-cert setup is never silently
affected). - Two low-severity silent-failure spots (
/metricsDB query, diagnostics
bundle NAS summary) now leave a debug-level trace instead of swallowing
the exception entirely. - New: send a recommendation straight to Radarr/Sonarr from Discovery.
A hand-off modal fetches the target instance's root folders and quality
profiles live, lets you pick monitored/search-now, and calls the
existing (previously unreachable from the UI) send-to-radarr/sonarr
endpoints - closing the biggest functional gap in the initial Discovery
ship, where this control was a non-interactive placeholder. - New: pagination and a streaming-provider filter on the Discovery page.
The list endpoint always supportedpage/per_pageand aprovider_id
filter, but the page fetched one fixed batch of 60 with no way to reach
anything past it, and the provider filter had no UI at all. A "Load more"
control and a provider dropdown (backed by a new
GET /recommendations/providers) close both gaps. - Discovery UI polish: an "Open on TMDB" link and TMDB-attributed
availability chips on every card, a "Copy TMDB ID" action, and a full
Discovery & Recommendations configuration section in Settings. - Fixed (GitHub issue #1): the NAS write-budget reservation charged a
same-directory rename (backup_existing_target's metadata-only,
zero-byteos.rename()) at full file size, since it only checked whether
the target classified as NAS/network rather than whether source and
target were on the same device. On the reporter's production instance
this exhausted a 300GB/day budget on phantom writes alone, then blocked
genuine replacements and discarded already-downloaded releases. Now
skipped whenever_same_storage_device()is true. - Fixed: a NAS failure cooldown was purely in-process, so a restart
right after a failure silently dropped it and let the next replacement
hit the same failing share immediately. Now restored from
StoragePathHealthon startup. - Fixed: the duplicate-cleanup recycle path
mkdir'd onto its
destination without preflighting it first; a misconfigured or
unreachable recycling-bin share is now checked before use, falling back
to skip-and-retry-next-scan instead of a permanent delete. - Fixed (GitHub issue #2): GHCR images weren't publishing for
latest
or any tagged version - CI's lint and test jobs were failing outright
(a missingpytest.iniplus 88 ruff findings), so the jobs that actually
push to GHCR never ran. Also fixed a latent race in the multi-arch Docker
build where the per-platform matrix job pushed directly to the same tags
as the manifest-merge job, lettinglinux/amd64andlinux/arm64builds
overwrite each other underlatest. - Fixed: a cross-device directory move onto a NAS/network target fell
through to a plain, unthrottledshutil.move()with no rate limit and no
budget accounting - the one path that bypassed every NAS safety control
this module exists to provide. Nothing in this release triggers it
(movies are single-file), so it now refuses loudly instead of moving the
bytes unsafely; a same-device directory move is unaffected. - Fixed: marking a recommendation as already-owned could be silently
reverted by the next refresh if the correlation check still couldn't see
it as owned (physical media, an unscanned library) - that state is now
protected the same way dismiss/hide/watchlist already were. - Fixed:
genres_include/genres_excludefiltering was permanently
dead code - sourced candidates always got an empty genre tuple, since
TMDB's collection/recommendations/similar payloads only carry numeric
genre IDs, never names, and nothing resolved them against TMDB's genre
list. Now resolved via a genre map fetched once per refresh. - Fixed: a recommendation that dropped below
minimum_scoreon a later
refresh was left frozen at its old score forever instead of expiring. - Fixed:
GET /recommendations'sprovider_idfilter ran in Python
after pagination and aftertotalwas computed from an unfiltered count,
so a page could come back empty (or split matches across pages) while
totalstill reported the unfiltered figure. Filtering now happens at
the SQL level before pagination. - Fixed: the same endpoint's Plex-ownership check ran two
SELECT count(*)queries per returned row; replaced with one batched lookup. - Fixed: a transient Windows file lock (e.g. Plex or an AV scanner
briefly holding a just-created file) during post-replacement cleanup
could permanently orphan the old file, since that cleanup step runs
once and nothing else ever retries it. Given the same retry the
move-into-place step already had. - Full audit findings:
docs/BACKEND_AND_RECOMMENDATIONS_AUDIT.md.
Competitive analysis:docs/ARR_PLATFORM_GAP_ANALYSIS.md.
Upgrading
No existing config key or database column changes meaning or shape - see
docs/UPGRADE_NOTES_2.0.0.md for the full standalone upgrade note. The new
recommendations: config block defaults to enabled: false, so nothing
changes on upgrade until you turn it on in Settings.
Windows installer
Download SlimarrSetup-2.0.0.0.exe below and run it - per-user install, no
admin rights required.