Fix stale download_path override and unsafe alphabetical pairing
in qbt-relink.sh Second live incident in the same batch: setLocation genuinely succeeded and save_path updated correctly, but content_path (what recheck actually reads) stayed pointed at qBittorrent's incomplete staging path via a leftover per-torrent download_path override from an earlier failed attempt. setLocation doesn't clear that override. Fixed by also calling torrents/setDownloadPath (note: takes "id", not "hashes") and verifying content_path directly before proceeding. Also replaced alphabetical-sort file pairing with SxxEyy-parsed matching, since sort order silently breaks on non-zero-padded episode numbers (E9 sorts after E10) - a real risk across the ~320 remaining folders with inconsistent naming conventions. Claude-Session: https://claude.ai/code/session_01HZQK6jHmdTpFjFZM8FUnqA
This commit is contained in:
@@ -64,15 +64,18 @@ bash ~/.claude/plugins/cache/claude-homelab/homelab-core/*/skills/qbittorrent/sc
|
||||
```
|
||||
|
||||
It **stops the torrent first** (qBittorrent 5.x renamed pause/resume to
|
||||
stop/start), sets its location to the season folder — verifying the change
|
||||
actually took effect before continuing, not just trusting a 200 response —
|
||||
renames each file to match Sonarr's output (paired by sorted order — always
|
||||
check the printed preview makes sense), then triggers a recheck, and leaves
|
||||
the torrent **stopped** afterward rather than auto-resuming. Since it's the
|
||||
same underlying data (hardlink, same inode), the hash check passes and the
|
||||
torrent is ready to seed normally again once you manually start it — no
|
||||
re-download needed. **The recheck reads the whole file over NFS and is
|
||||
slow** (minutes per multi-GB file) — kick off several in parallel rather than
|
||||
stop/start), sets its location *and* download-path override to the season
|
||||
folder — verifying both actually took effect before continuing, not just
|
||||
trusting a 200 response — pairs and renames each file to match Sonarr's
|
||||
output (by parsed `SxxEyy` episode number, not sort order — see below), then
|
||||
triggers a recheck, and leaves the torrent **stopped** afterward rather than
|
||||
auto-resuming. Since it's the same underlying data (hardlink, same inode),
|
||||
the hash check passes and the torrent is ready to seed normally again once
|
||||
you manually start it — no re-download needed. **The recheck reads the whole
|
||||
file over NFS and is slow** (minutes per multi-GB file, and this qBittorrent
|
||||
instance seems to only actively process one or two full-file rechecks at a
|
||||
time — others sit at `stoppedDL`/0% "queued" looking identical to a real
|
||||
failure until their turn comes) — kick off several in parallel rather than
|
||||
waiting on each one serially, and poll with:
|
||||
|
||||
```bash
|
||||
@@ -90,6 +93,43 @@ own `Season NN` folder — don't try to relink multiple torrents to one shared
|
||||
show-root folder, since the tool matches file counts 1:1 between the torrent
|
||||
and the destination folder.
|
||||
|
||||
**Known limitation**: if Sonarr split a single torrent's files across two
|
||||
destination folders (e.g. a season pack that included specials, which Sonarr
|
||||
routed to a separate `Specials`/`Season 00` folder), `qbt-relink.sh` can't
|
||||
handle that in one call — it only knows about one `<new-folder>`. Check the
|
||||
file count first (`torrents/files` count vs. `ls` count in the season
|
||||
folder); if they don't match because of a specials split, this needs doing
|
||||
by hand (or extending the tool) rather than forcing it.
|
||||
|
||||
### Incident 2: a stale `download_path` override kept recheck pointed at the wrong place entirely
|
||||
|
||||
Even after incident 1's fix (checked HTTP status, confirmed `save_path`
|
||||
via a follow-up GET), three of the nine torrents in the same batch
|
||||
(Babylon 5 S03/S04/S05) still failed — `setLocation` genuinely succeeded and
|
||||
`save_path` genuinely updated, but their **`content_path`** (what qBittorrent
|
||||
actually reads during a recheck) stayed pointed at
|
||||
`/data/torrents/incomplete/video/tv`, qBittorrent's global incomplete-files
|
||||
staging path (`temp_path`, from `app/preferences`). Cause: earlier in the
|
||||
same incident, these three torrents had briefly been flagged as needing to
|
||||
download again (a race between the bad first relink attempt and this
|
||||
corrective one — see the qBittorrent log via `/api/v2/log/main` for
|
||||
`"Torrent move canceled"` / duplicate `"Start moving torrent"` entries if
|
||||
this happens again), which set a **per-torrent `download_path` override**
|
||||
that `setLocation` does not clear. `content_path` silently followed that
|
||||
stale override instead of `save_path` — so the recheck kept validating
|
||||
against an empty folder and would have re-downloaded again, exactly like
|
||||
incident 1, had it not been caught by watching state directly rather than
|
||||
trusting the script's "Done" message.
|
||||
|
||||
Fix: `torrents/setDownloadPath` (note — takes `id`, not `hashes`, unlike
|
||||
every other endpoint used here) clears the override, and `qbt-relink.sh` now
|
||||
calls it and verifies `content_path` (not just `save_path`) actually landed
|
||||
under the target folder before proceeding to rename/recheck. **If a torrent
|
||||
ever seems stuck at `stoppedDL`/0% far longer than others in the same batch,
|
||||
or its `state` is `checkingDL` instead of `checkingUP`**, check
|
||||
`content_path` vs `save_path` directly — a mismatch means the recheck is
|
||||
running against the wrong location and will "succeed" at finding nothing.
|
||||
|
||||
### Incident: an unchecked `setLocation` call let a torrent start re-downloading
|
||||
|
||||
The first version of `qbt-relink.sh` fired `setLocation`/`renameFile`/
|
||||
|
||||
Reference in New Issue
Block a user