Articulate. Home Famflix StudioServer Playbook Failures pipeline
Famflix · how it runs · v6.0 · 2026-08-14

Every destination, every priority, measured on the box.

v301 described a system that had already stopped working. v400 documented the repair but not the system. v5 is the map: where every byte lands, what gets acquired first, and what is still broken. Nothing here is carried forward — every number was read off the Studio today.

Measured state

VolumeSizeUsedFreeRole
/Volumes/PERSONAL3.6 TB320 GB3.3 TBall new writes — library /data3 + all downloads
/Volumes/MEDIA7.3 TB6.4 TB936 GBlegacy library /data
/Volumes/MEDIA27.3 TB6.8 TB453 GBlegacy library /data2 — no new writes
/Volumes/2TB1.8 TB1.2 TB648 GBdocker configs · music library · Kometa
/Volumes/2TB 11.8 TB465 GB1.4 TBunused second disk — July docker copy only
Measured
Radarr1,863 movies · 1,034 with file (973 at start of pass) · roots /data2 906, /data3 869, /data 88 · queue 21
Sonarr922 series · 5,624 / 20,449 episodes · 1,867 monitored-missing · queue 34
IndexersProwlarr 10, all passing test (was 6, of which 1 working)
Plex1,735 movies · 262 shows · 2,347 artists · 7,534 albums
Transmissioncap 20.48 MB/s · slot ceiling raised 20 → 50, peers 240 → 500 · dir PERSONAL
There is a second 2 TB drive nobody is using. /Volumes/2TB 1 is /dev/disk13s1 — a separate physical disk with its own UUID, 1.4 TB free, holding a July copy of the docker tree. It appears in no capacity plan and no script. Total pool free is therefore 6.4 TB, not 5.0.
Radarr can only see half the movie library. Radarr tracked 973 files at the start of the pass; there are ~1,950 movie folders on disk. 978 folders / 2.6 TB are untracked — 319 with tracker-junk names, 659 with clean names (The Batman, John Wick 4, Gladiator II, Avatar: The Way of Water). Untracked means unrenamed, unupgradable, and unmatched in Plex. A manual-import pass began today: 268 matched, 199 imported; the remaining 781 return "Unknown Movie" and need adding to the library first.

Every destination

ContentContainer pathHost pathIn Plex
New movies/data3/media/movies/Volumes/PERSONAL/media/moviessec6 Movies
New TV/data3/media/tv/Volumes/PERSONAL/media/tvsec7 TV Shows
Music (from slskd)/Volumes/2TB/data/media/musicsec12 Music
Torrent downloads/downloads/Volumes/PERSONAL/data/downloads
In-progress/Volumes/PERSONAL/data/downloads/.incomplete
slskd albums/downloads/Volumes/PERSONAL/data/downloads/slskd
Legacy movies/data · /data2MEDIA/data · MEDIA2/datasec6
Personal media/Volumes/PERSONAL/personal/{tv,music}sec10 · sec11

The mapping that matters: /data3/Volumes/PERSONAL, the volume root — not /Volumes/PERSONAL/data. Plex watches /Volumes/PERSONAL/media/*, so anything written to PERSONAL/data/media is invisible to it. Remote path mapping in both *arr apps translates /Volumes/PERSONAL/data/downloads//downloads/; without it every import fails with path does not exist.

MEDIA-MIRROR does not exist. Older docs describe it as an rsync backup target. There is no mirror and no backup of anything. The library is single-copy.

Acquisition priority

#TierOutstandingSize
1Missing episodes — gaps in series already owned1,885 eps~940 GB
21 series within 5 episodes of complete68 eps~34 GB
2Seerr requests unfulfilled80
3New / trending movies (2025+)577~2.3 TB
4New / trending TV — future episodes only730 seriesas aired
5Catalogue movies — Top 250, pre-2025285~1.1 TB
The ordering is notional, not enforced. Those tiers describe what is monitored. Sonarr and Radarr search on their own schedules and hand everything to Transmission, which is strictly FIFO. Marking something urgent upstream does not move it up in the download client. Making tier 1 genuinely first requires reordering the Transmission queue.

Backlog hygiene applied today: Sesame Street held 3,702 phantom episodes with zero files; X-Play another 902. Twenty further series were pruned — those with files were unmonitored and kept, those with none were removed. Monitored-missing fell 9,336 → 1,885 without deleting a single file.

Sources & lists

Trakt was lost in the June v100 rebuild — the fresh Radarr config dropped four working lists and their tokens, and nothing noticed for ten weeks. Re-authed today. Radarr now runs Trakt Trending, Popular, Anticipated and Box Office; Sonarr runs Trending, Popular and Anticipated TV. All limit 500, auto-add, and — for the first time — searchOnAdd = true. Previously every list added titles and never searched for them.

Active: the seven Trakt lists · IMDb Top 250 · TMDB Popular · TMDB Top Rated · Latest Releases · Latest TV Shows.
Dormant (built, deliberately off until the priority queue clears): Netflix, Amazon Prime, Hulu, Disney+ movies; Netflix, HBO, Amazon Prime, Hulu, Disney+, BBC shows.

A release profile on both apps now blocks fake and non-English rips: regex for Cyrillic and Devanagari runs, plus FRENCH-STREAM, DCPRIP, TS.RUS, HDTS, CAMRip, HDCAM and \bTLR\b. Written after a re-search pulled back the same Russian-dubbed fakes that had just been deleted.

Kometa — collections

Plex holds 88 collections built by Kometa: IMDb Top 250 and Popular, TMDb Popular / Top Rated / Trending, Newly Released, and per-service rows for Netflix, Prime Video, HBO Max, Disney+, Hulu, Apple TV, AMC+, Peacock and tubi.

Every one of them was a frozen snapshot. Kometa last completed a real run on 2026-07-14 (1m42s). On 18 July its config.yml was replaced by an unconfigured default template — Plex URL 192.168.1.12, blank token, blank TMDB key. Every nightly run since aborted in under one second on Config Error: tmdb sub-attribute apikey is blank, and because the container is restart: "no" nothing ever surfaced it. "IMDb Top 250 — 39 movies" was never a library gap; it was a collection that stopped updating a month ago.

Rebuilt 2026-08-14: real config written (Studio URL, Plex token, TMDB key), collections.yml synced from ~/kometa, image pulled 2.4.4 → 2.4.7, and both Movies and TV Shows now load default: imdb and default: streaming alongside the curated file. First clean run connected to both libraries with zero config errors.

Kometa is not in the famflix v100 compose — it still lives in the older ~/docker/docker-compose.yml under a scheduled profile. That split is why it drifted unnoticed and should be consolidated.

Goals

TargetNowGoalGapSpace needed
Movies1,7353,0001,265~5.1 TB @ 4.0 GB avg · ~3.2 TB @ 2.5 GB
Episodes8,18610,0001,814~0.9 TB @ 0.5 GB avg
Albums7,53410,0002,466~0.5 TB @ 0.21 GB avg

Reachable, but only on two conditions. At the current 4.0 GB movie average the three gaps need ~6.5 TB against 6.4 TB free — no margin. Dropping the movie quality target to ~2.5 GB brings it to ~4.6 TB and leaves comfortable headroom. Second: the album want-list holds 1,008 remaining candidates against a 2,466 gap — 10,000 albums is arithmetically impossible until that list is expanded by roughly 1,500.

At a saturated 20.48 MB/s the box moves 1.77 TB/day, so 4.6 TB is under three days of pure throughput — realistically one to two weeks at real-world peer speeds.

Requests — the Seerr backlog

786 requests. 785 from one account. Seerr was built for ~30 friends and family; anthonybooth made 785 of the requests and lieslrad made one (The Dark Tower, already available). Whatever the sharing plan was, it never happened.

StateCountMeaning
Available56772% — delivered and in Plex
Approved / processing161accepted, never found
Approved / partial38TV, some seasons only
Failed12errored during the full-disk period
Duplicates6same title requested twice
137 requested movies had never been searched for. Not rejected — never attempted. 128 sat in Radarr monitored with no file, 2 were on the wrong root, and 9 were not in Radarr at all despite Seerr showing them as approved. This is the visible residue of the /data2 full-disk period: requests were accepted into a folder that could not hold them, and the failure never propagated back to the request.

Cleared 2026-08-14: 9 movies added on /data3, 2 re-rooted, 115 released titles searched in six batches, 22 announced-but-unreleased left monitored with no search. Four large network shows (NCIS, Grey’s Anatomy, Supernatural, Law & Order — 1,500+ episodes between them) were declined deliberately, not failed.

Indexers — the real acquisition ceiling

Radarr was searching one indexer. The log line Searching indexers for [X]. 1 active indexers is the whole story. Three were configured; Knaben was failing, YTS had been failing over six hours, 1337x had been dead since 28 June and was never synced into Radarr at all, and TorrentGalaxyClone had no definition. One public tracker cannot fill a back catalogue.
IndexerBeforeNow
The Pirate Bayworkingworking
Knabenfailingpassing
YTSfailing >6hpassing
EZTVworking (TV)passing
LimeTorrentsadded
Internet Archiveadded
TorrentsCSVadded
TorrentProject2added
TorrentByteadded via FlareSolverr
kickasstorrents.wsadded via FlareSolverr
1337xdead since 28 Junremoved — origin IP ban, FlareSolverr cannot bypass
TorrentGalaxyCloneno definitionremoved

FlareSolverr was running the whole time and no indexer was tagged to use it. The proxy existed, the container was solving Cloudflare challenges on demand, and the tag linking the two was never applied to a single indexer. Tagging it unlocked two trackers immediately; torrentcore, extratorrent and kickasstorrents.to still fail on Forbidden or dead DNS rather than Cloudflare.

Debug playbook

The full ordered procedure for taking Famflix from “nothing is landing” to proof that it is. Every step below found a real fault on 14 August 2026, when the pipeline had been dead for 34 days and four separate monitors all reported healthy. Run them in order — each layer’s answer changes what the next layer means. Also published standalone at /debug.html.

Zeroth law

A · Reach the box

B · Storage — always first

C · Paths — the single largest source of faults

  • Reconcile four layers, in this order, and expect drift between all of them:
    1. Plex library Locations
    2. arr root folders (/data, /data2, /data3)
    3. Container volume mounts in docker-compose.yml
    4. Hard-coded constants inside .py helper scripts
  • A volume the container cannot see cannot be written to, however much free space it has. /Volumes/PERSONAL had 3.6 TB free and was mounted into nothing.
  • Download client path and *arr path must agree, or you get “downloaded, never imported”. Set remote path mappings if they can’t.
  • Check every root the app knows about, not just the default — movies were scattered across three roots with no rule.
  • Never move an in-flight torrent with transmission-remote --move. It corrupts pieces and leaves completed torrents reporting “No data found”.
  • After any compose edit: back up, edit, up -d, then re-read the root folders from the API to confirm the app actually sees the new mount.

D · Host performance

  • Free RAM is not available RAM on macOS. Inactive pages are reclaimable. A dashboard reading “swap pressure 100%” was measuring allocation, not activity — a false alarm that nearly triggered a pointless restart.
  • Use memory_pressure and the swapout rate over a window. A cumulative swap counter tells you nothing about now.
  • Check the app’s own thread health. Kestrel logging “heartbeat has been running for 00:00:07” means thread-pool starvation inside Radarr, not a sick host.
  • Watch OrbStack import I/O separately — a large manual import can saturate it while the host looks idle.

E · Seerr (Overseerr)

  • Pull every request via the API, not the web UI — the public URL sits behind Cloudflare and 403s to anything scripted.
  • Read request.status and media.status. They disagree constantly. Approved + processing can mean “nothing has ever been searched for this”.
  • Bucket the whole list: available / processing / partial / failed / declined. The interesting number is approved but not available — 137 movies and 77 TV, some over a year old.
  • Check Seerr’s activeDirectory for each *arr. This was the root cause of the 34-day stall: it pointed at a volume with 126 MB free, so every single request was born into a folder that could not accept it.
  • Verify the default quality profile and root folder Seerr pushes on new requests — fixing existing ones doesn’t fix the next one.
  • Cross-reference every non-available request against Radarr/Sonarr by TMDB id. Expect three failure classes: not in the app at all, present but unmonitored, present and monitored but never searched.
  • Audit who is actually using it. 785 of 786 requests came from one account — the “friends and family” assumption was wrong.
  • Deduplicate. Six titles were requested twice.
  • Decline what you don’t actually want before searching. Four network shows would have pulled 1,500+ episodes.
  • Retry failures only after the underlying cause is fixed — a retry into a full disk just re-fails and burns the record.

F · Radarr / Sonarr

  • Read /api/v3/health first. It names failing indexers and broken paths in one call.
  • Read /api/v3/command. The command queue is single-threaded. One 199-file ManualImport monopolised it for 40+ minutes, stacked 24 commands behind it, and left every completed download at importPending. That, not the downloads, was “nothing is landing”.
  • If the queue is jammed, cancel the backlog rather than waiting. Queued commands do not time out.
  • Compare library count against files on disk. 978 movie folders / 2.6 TB were untracked by Radarr entirely — “Radarr can only see half your library” was literally true.
  • Check monitored and hasFile separately. Unmonitored-and-missing is invisible to every wanted list.
  • Check isAvailable before firing searches. Announced-but-unreleased titles waste indexer budget forever — 22 of the outstanding requests were unreleased.
  • Batch MoviesSearch in groups of ~20 with a pause. One command with 115 ids blocks the queue you just cleared.
  • On PUT /movie/{id}, id is read-only in the body. Sending it returns request.body.id is read-only.
  • Sonarr: read episodeCount vs episodeFileCount per series. The gap is real missing episodes; totalEpisodeCount includes specials and unaired and will terrify you for no reason.

G · Indexers — check the count, not the config

  • The line that matters is in the Radarr log: Searching indexers for [X]. N active indexers. Configured ≠ active. Three were configured; one was working.
  • Read /api/v3/health on each *arr for “Indexers unavailable due to failures” and “…for more than 6 hours”.
  • Read Prowlarr /api/v1/indexerstatus for disabledTill. An indexer can be enabled in the UI and disabled in reality until tomorrow.
  • POST /indexer/test on every indexer individually. Failures sort into four kinds, each with a different fix:
    • Cloudflare protection → route through FlareSolverr
    • Name does not resolve → dead domain, needs a live mirror
    • Forbidden → IP or UA blocked
    • Definition does not exist → remove and re-add
  • FlareSolverr only works on tagged indexers. It was running and solving challenges all along; not one indexer carried the tag. Create the tag, attach it to the proxy, then attach it to each Cloudflare-blocked indexer.
  • Add indexers by definition name, test, and delete the ones that fail the test — a broken indexer in the pool slows every search.
  • Confirm Prowlarr → app sync actually happened. An indexer can be healthy in Prowlarr and absent from Radarr. Fire ApplicationIndexerSync and re-read the app’s indexer list.
  • Sync is per-app: an indexer with TV-only categories will appear in Sonarr and not Radarr. That is correct, not a fault.
  • Watch which indexer supplies your junk. Persistent .nfo-only torrents traced to one source, surfacing via an aggregator.

H · Transmission & throughput

  • Do not trust the speed cap as the explanation for slow. Compute MB per active slot: speed ÷ active torrents.
  • If MB/slot is low (0.4–0.6) and slots are pinned at the ceiling with torrents pending, the ceiling is the bottleneck, not bandwidth. Raise SLOT_MAX and the peer limits.
  • Establish a single owner of Transmission settings. An agent writing session-set every 60 s will silently overwrite anything you change in settings.json or the UI.
  • Transmission RPC rejects floats. 20.0 × 1024 = 20480.0 is refused; cast to int.
  • Never except: pass around an RPC call. One swallowed exception hid a rejected speed setting for hours — the cap read 20, the box ran 8.
  • Check the zombie-prune window. Torrents delivering no video get pruned after 30 min, so the failure never surfaces as an error — it surfaces as silence.
  • Verify torrents actually contain video. A completed torrent of .nfo and .txt imports as nothing and reports success.

I · Import & naming

  • Anything stuck at importPending is a command-queue or path problem, never a download problem.
  • Run manual import in small batches. One giant batch is the single-threaded queue jam described in F.
  • Verify content matches title with ffprobe on format_tags.title — that is how “Shame is actually Submarine” was proven rather than guessed.
  • Hunt tracker junk in filenames (www.SITE.org - Title). It is the main cause of Plex refusing to match an item, which presents to you as a missing poster.
  • Look for TV episodes sitting under the movie roots. They import as nothing and inflate the untracked count.
  • Clear metadata-only folders — a folder with an .nfo and a poster and no video reads as “have it” to a human and “missing” to the app.
  • When deleting by title match, print the exact list and count rows the way the human is counting them. An off-by-one on a header row cost eight series; an over-broad title match deleted two good films.

J · Plex & Kometa

  • Missing posters are almost never a network fault. Check unmatched items first — the cause is filename junk, not IPv6, not DNS.
  • Kometa with restart: "no" and a config error dies in under a second and leaves nothing behind. It had been dead since 18 July on a blank TMDB apikey.
  • Read the Kometa log for Config Error before assuming it ran. Success and never-started look identical from outside.
  • Validate the config actually has: Plex URL + token, TMDB apikey, a generous timeout, and no unsupported mass-update keys.
  • Prove Kometa worked with a collection count, not a log line. IMDb Top 250 went 39 → 236 items; collections 88 → 99.
  • A collection that reports a small number is usually a library-matching failure, not a missing-media failure.

K · Music

  • Check the importer’s hard-coded source directory matches where slskd is actually writing. It didn’t.
  • Gate imports on a completeness ratio (tracks present ÷ tracks expected), with a staleness escape hatch, or you import half-albums forever.
  • Add a no-manifest fallback for albums with no track count, or they never import at all.
  • Prove throughput with the Plex album count before and after, not with the importer log.

L · Scripts & monitors

  • Grep every .py for hard-coded paths after any storage change. Thirteen still referenced the old download directory.
  • Back up before editing, with a dated suffix, every time.
  • Audit the monitors themselves: does each one report a reason alongside a zero? If not, it cannot detect this class of outage.
  • Counters worth having that were missing: Transmission active/completed, *arr queue depth, *arr import failures, swapout rate.
  • Beware Python footguns hit today: urllib.request.quote (it’s urllib.parse.quote), globs in redirect targets, and parsing transmission-remote -l with awk instead of using RPC.

M · Close the loop — the proof step

  • Nothing is fixed until a number moves. Collect, in this order:
    1. A grab timestamp in /api/v3/history?eventType=1 for a title you specifically chose
    2. That title present in the download queue with a non-zero percentage
    3. An import into the library
    4. The item visible in Plex
  • Re-run the same measurement an hour later. A one-off grab is not a working pipeline.
  • Flag anything you cannot explain rather than smoothing it over — 93.6 GB of disk use vanished during the proof window and still has no cause.
  • Write down what is still broken. A runbook that only lists wins is a marketing document.

Fixed today

FaultCauseProof
34-day pipeline stallOverseerr default root = /data2, 126 MB free0 → 111 torrents, 8→20 MB/s
PERSONAL unusednot mounted into any container3.3 TB now in service
Imports failingremote path mapping still on 2TBmovies + episodes importing again
Albums stalledmanifest keyed on requested name, slskd uses peer's folder namePlex 7,463 → 7,534
Cap stuck at 8 MB/sthroughput-agent.py rewrote it every 60s; float value rejected and swallowed by except: pass20,422 kB/s measured
Trakt absentlost in v100 rebuild; api.trakt.tv IPv6-only in containers7 lists live, +70 movies first sync
Kometa dead a monthconfig replaced by default template, blank TMDB key2.4.7 running, both libraries connected
Movie library half-invisible978 folders never adopted by Radarrmanual import: 973 → 991 files and climbing
Radarr searching 1 indexer3 of 4 indexers failing; FlareSolverr never tagged; Prowlarr never synced 1337xpool 6 → 11, 10 passing test
137 requests never searchedresidue of the /data2 full-disk period; 9 absent from Radarr entirely115 searched, 10 grabs in 35 min
Speed stuck at 7–8 MB/snot the cap — SLOT_MAX = 20 at 0.4–0.6 MB/slot with 47 torrents pendingSLOT_MAX 50, peers 500; slots stepping 20 → 25 → …
Sicario + Irrational Man failednever added to Radarr; failed under full diskgrabbed 13:59:54 and 13:59:57
1337x permanently failingorigin IP ban on the Studio, not a Cloudflare challengeremoved; pool 10, all passing
3 requests could never searchno release date at all, so minimumAvailability: released was unsatisfiableswitched to announced, searched
6 duplicate Seerr requestssame title requested twicemerged, keeping the better media state
93.6 GB "vanished"not a leak — 36 Radarr Upgrade replacements deleted 124.3 GB of old filesOppenheimer 3.57→2.17 GB, Barry Lyndon 9.48→5.62
227.2 GB orphanedpruner removed torrents with delete-local-data: False, leaving 53 partials nothing trackedreclaimed; PERSONAL 433 → 320 GB used
Pruner orphaning datadead / preflight / zombie / cap prunes all left their partials behindall four now delete local data; completed sweep still preserves
throughput-agent.py stale pathDOWNLOADS still pointed at /Volumes/2TB/data/downloadsrepointed to PERSONAL
Transmission dying 5×/dayTR_URL used localhost, which resolves to IPv6 ::1 first — Transmission binds IPv4-only 0.0.0.0:9091handshake 2.57s → 0.0004s; unreachable events 15/day → 0
Self-inflicted false crashesI raised curl --max-time 10→25 without raising the Python subprocess timeout=15 that wraps itboth now 25s / 35s; no false "unreachable"
Wrong Transmission credentials3 scripts used transmission:transmission, the other 50 use admin:admin01auth-rejection storm in the daemon log ended
OrbStack capped at 4 GB9 containers sharing 4,096 MiB on a 36 GB box; Radarr at 119% CPU logging Kestrel thread-pool starvation; largest process in all 5 jetsam killsraised to 14,336 MiB; Radarr CPU 119% → 4%; commands now run in parallel
Radarr import queue jammedsingle-threaded queue + a 199-file ManualImport queued 11:30, started 15:34; ProcessMonitoredDownloads stacks one/min; queue persists in the DB across restarts; started commands return 409 on cancelpurged 59 commands; 9 movies moved into the library directly and adopted
Music backlog stuckgate had no escape hatch — albums below 70% waited foreververy-stale rule (24h, 6+ tracks); Plex albums 7,991 → 8,004
22 torrents erroredcorrupt pieces from jetsam kills mid-write; 15 "No data found" were already move-importedverified and restarted; errors 22 → 0
~810 GB reclaimed3 untracked duplicate series, Russian/Indian titles, GoT .part filesMEDIA2 126 MB → 455 GB free

Known-broken

  • 978 movie folders / 2.6 TB untracked by Radarr. Manual import started; 781 still return "Unknown Movie".
  • 15 Plex movies unmatched — tracker prefixes and mangled punctuation in filenames, so no poster.
  • 13 scripts still read /Volumes/2TB/data/downloads, the directory that moved today. Plus four dead paths.
  • storage-audit.py ROOTS omits MEDIA2 — reported files_scanned: 0 while MEDIA2 was full.
  • The 8899 dashboard measures Plex deltas only. It cannot distinguish "nothing downloading" from "everything downloading and failing to import" — both read +0. Needs Transmission active/completed, *arr queue depth, import failures, and swapout rate.
  • No IPv6 transit — the host holds 10 IPv6 addresses and a default route with no upstream. Most clients fall back; .NET in containers does not. Trakt is pinned to IPv4 in compose and will break when Cloudflare rotates.
  • Album target unreachable — 1,008 candidates remain against a ~2,500 gap to 10,000.
  • 13 errored torrents — 4 corrupt mid-download, 9 completed but reporting "No data found" after a location move I ran. They need verify-or-remove.
  • TV episodes sitting in the movies folder — talk-show and series files found under the movie roots during import triage.
  • Kometa lives outside the v100 compose, on a scheduled profile with restart: "no" — a silent failure mode by design.
  • torrentcore, extratorrent.st, kickasstorrents.to return Forbidden or fail DNS; FlareSolverr does not help.
  • 22 requested titles are unreleased — armed and monitored, first is Tony (14 Aug), last is From the Ashes (Jun 2027). Nothing to do but wait.
  • Radarr’s command queue is single-threaded and DB-persisted. Any long ManualImport blocks every other command, ProcessMonitoredDownloads stacks one per minute behind it, a container restart reloads the whole backlog, and a started command cannot be cancelled (409). Submit imports in small batches or bypass the queue.
  • Music: 89 abandoned 1–5 track fragments / 5.9 GB in slskd, 29 days old. They will never complete.
  • 249 GB still at /Volumes/2TB/data/downloads — the old rsync source, superseded.
  • No backup.

Operating rules

  • Reconcile paths before diagnosing. Plex Locations → *arr root folders → container mounts → script constants. Every failure today was drift between those four.
  • A monitor that reports +0 without a reason is not a monitor. Bandwidth flowed for five weeks while the only signal said nothing was happening.
  • Trust the filesystem over the library index. du found 351 GB of duplicates that sizeOnDisk could not see.
  • Never swallow an exception. One except: pass hid a rejected setting for hours.
  • Never use localhost in a service URL on this box. It resolves to IPv6 ::1 first and Transmission binds IPv4-only. Always 127.0.0.1.
  • A wrapper timeout must exceed the timeout it wraps. subprocess(timeout=15) around curl --max-time 25 guarantees a false failure.
  • Free RAM is not available RAM. Check memory_pressure and swapout rate, never cumulative counters.
  • Count active indexers, not configured ones. The Radarr log states the active number on every search. Configured and working are different facts.
  • Nothing is fixed until a number moves. Grab timestamp, queue percentage, import, visible in Plex — in that order.