Repository navigation
fix(download): do not cancel a queued torrent as stalled - #1420
Merged
calibrain merged 4 commits intoOct 3, 2026
Merged
Conversation
qBittorrent only runs a few downloads at once (3 by default) and holds the rest as queuedDL. A queued torrent reports the same status on every poll, and the stall timer only counts a changed status or progress as activity, so a torrent that was just waiting for a slot was cancelled after five minutes. A queued torrent now asks for an activity grace, renewed every ten minutes, and releases it as soon as it leaves the queue. There is a two hour ceiling so a queue that never moves still ends.
The terminal hook copies the task's status message into the history row, and the
stall timer set its message after cancelling. The row kept whatever the last poll
said ("Queued"), so a download the timer ended looked the same as one a person
cancelled. The message is now set before the cancel.
The stall timer waits five minutes for a change in progress. Torrents are jerky: a swarm with one seed can sit still for several minutes and then carry on, so a slow but live download was cancelled and left behind. Each time a torrent's progress goes up it now asks for a 15 minute activity grace, which restarts from that moment, so a torrent is only called stalled 15 minutes after it last moved. One that never moved (a magnet that cannot fetch metadata) keeps the five minute window, and one that has stopped does not get more time.
The orchestrator's 300s stall timer cancelled torrents that needed longer than five minutes to fetch metadata or find a first peer, before any progress existed to extend the window. A torrent now gets one MOVING_STALL_SECONDS grace the first time it is seen outside the queue, and each later step forward renews it as before.
Owner
|
Thank you |
calibrain
pushed a commit
that referenced
this pull request
Oct 3, 2026
Cancelling a torrent download leaves the torrent in the client. `_safe_remove_download` documents the rule: "torrents: never remove or delete client data (avoid breaking seeding)". That makes sense for a torrent that has data. A torrent that is still at 0% has nothing to seed and nothing to resume, and leaving it behind holds a download slot in qBittorrent's queue or sits there as a dead entry. I hit this on a qBittorrent that is shared with Sonarr, Radarr and Lidarr and has a download limit. Shelfmark cancelled downloads that were queued (#1420) and left them in the client. Three torrents that never fetched metadata held every active slot, and each torrent added after them waited behind them. Removing those by hand freed the slots. This removes the torrent and its files when a download is cancelled, Shelfmark added the torrent, and the client reports 0% progress. A torrent with any data is left alone as before. So is one that was already in the client when the download started, since Shelfmark didn't add it. If the removal fails it is logged and the cancel carries on. Tests cover removal at 0% for a queued and a downloading torrent, leaving one that has data, leaving one the user already had, and a failing removal. The full suite passes, and I broke each rule on purpose to check a test catches it. This changes a rule you wrote down, so I've kept it apart from the queue fix. If you'd rather have it as a setting, or only remove a torrent that is still queued or fetching metadata, I'm happy to rework it.
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
qBittorrent only runs a few downloads at once (
max_active_downloadsdefaults to 3) and holds the rest asqueuedDL. Shelfmark's stall timer cancels a download after five minutes without a changed status or progress. A queued torrent reports "Queued" on every poll, so it looks idle, and Shelfmark cancels a download that was only waiting for a slot.I run Shelfmark against the same qBittorrent that Sonarr, Radarr and Lidarr use, which I assume is a common setup. Their torrents and Shelfmark's share one limit, so anything that fills the slots makes Shelfmark's torrent wait. In my case three torrents that never fetched metadata held every slot. I'd expect a busy Sonarr queue to hold them the same way, but I haven't reproduced that. Once the stall timer had cancelled the waiting downloads they stayed in the client, still queued behind the same blockers. On my instance 10 AudioBookBay downloads were cancelled while qBittorrent still had them queued.
This changes the torrent poll loop. When the client reports a queued torrent, it asks for an activity grace (the mechanism
html_get_pagealready uses for protection bypasses) and releases it as soon as the torrent leaves the queue. The grace is renewed every ten minutes and stops at two hours, so a queue that never moves still ends. A torrent that is downloading and moving is timed as before until the new window below applies.The second commit sets the stall message before the cancel runs. The terminal hook copies the message into the history row, and it was set afterwards, so a download the timer ended was recorded with the last poll's "Queued". That left no way to tell it apart from a person cancelling.
The last two commits are about slow torrents. The timer only counts a change in progress, so a torrent that needs more than five minutes to fetch metadata or find its first peer is cancelled before it has any progress to count, and one that moves a few megabytes at a time can be cancelled between bursts. I hit this with a torrent that had a single peer. A torrent now gets one 15 minute window the first time it is seen outside the queue, and each step forward in progress renews it. One that makes no progress for 15 minutes is still cancelled, so a dead torrent now takes about 15 minutes to end instead of five. That trade is the part I'm least sure about, so the number is easy to change.
Tests cover the grace being requested once, released when the torrent starts, renewed, and capped, the order of the message and the cancel, and the start and movement windows. The full suite passes, and I broke each rule on purpose to check a test catches it.
The two hour ceiling is a guess. If you'd rather have a setting for it, or a different number, I'm happy to change it.