The Download Is Not Done When It Is Grabbed

Sonarr's relationship with a download client does not end when the client accepts a release. This chapter follows the tracked-download state machine that turns an external client item into a Sonarr import decision. The focus is polling, context reconstruction, path validation, completion and failure states, and manual escalation. The reader should be able to explain why a client can report “complete” while Sonarr still says “import pending” or “import blocked.”

The reason is ownership. The download client owns the transfer and reports what it knows about its item. Sonarr owns the relationship between that item and the library's series and episodes. To make a durable change, Sonarr must observe the item again, recover enough identity context, and verify that its output path can be processed by the running installation.

Polling turns a client item into a tracked object

Sonarr periodically queries the download clients whose handling is enabled. Each client returns items with an external download identifier, title, category, total and remaining size, status, output path, and capabilities such as whether files can be moved or the item can be removed. Sonarr turns those observations into tracked downloads and keeps a cache of them so the rest of the application can reason about the item between polling cycles.

Polling is necessary because the grab event is a point-in-time fact. It says that a client accepted a release; it does not contain the client's entire future. The item may still be downloading, may fail, may become encrypted, may finish in a different path, or may finish with files Sonarr cannot map. Each refresh supplies a new observation that can move the tracked object to a different state.

The monitoring service does not wait for every possible event before checking. It queues a high-priority refresh when a release is grabbed, imported, or marked as requiring manual interaction, and it debounces those triggers so several nearby events do not create a burst of identical refreshes. It also filters out items that are already imported, failed, or ignored, while retaining items that still need tracking. A completed item can therefore leave active tracking only after the processing stage has established the corresponding terminal outcome.

This arrangement gives the system a controlled rhythm. The client remains the source of current transfer status. Sonarr's tracked object becomes the source of current reconciliation status. The two views can disagree temporarily without either being meaningless.

A tracked download is therefore a reconciliation cache, not a second copy of the client's internal database. On one refresh, the client may report an item as still downloading; on a later refresh, the same external identifier may report completion or failure. Sonarr updates its tracked object and lets the processing command decide which transition follows. If an item disappears from the client's current list, Sonarr can stop treating it as an active, trackable item without rewriting the history of what was previously observed. That separation keeps transient polling gaps from being confused with a new library fact.

The refresh trigger also has a causal role. A grab event makes a new item worth checking, an import event can change what remains trackable, and a manual-interaction event says that another observation or correction may be needed.