Skip to content

Retry with backoff when a torrent completes with zero files - #394

Open
BasterdOperator wants to merge 1 commit into
sirrobot01:mainfrom
BasterdOperator:fix/instant-cache-empty-files
Open

BasterdOperator wants to merge 1 commit into
sirrobot01:mainfrom
BasterdOperator:fix/instant-cache-empty-files

Conversation

@BasterdOperator

Copy link
Copy Markdown

What

Adds a short, bounded retry (5 attempts, 2s/4s/8s/16s/16s backoff, ~30s total)
in processTorrentDownload that re-fetches the torrent from its active debrid
provider when entry.GetActiveFiles() comes back empty, before giving up with
"no valid download links available".

Why

Some debrid providers (Premiumize in particular) can flip a transfer's status
to "finished" before the file's actual download link has been generated on
their side. This is most noticeable for content that's already cached and
completes in well under a second - the very first status check right after
submission can race that window and see zero files, even though the provider
confirms a valid link for the same file moments later.

Observed with Premiumize on already-cached single-file torrents (software
ISOs/installers). Example from my own logs:

16:35:19 | Processing torrent Action=download ... Name=debian-13.6.0-amd64-netinst.iso
16:35:21 | Entry: debian-13.6.0-amd64-netinst.iso submitted to Premiumize id=oqegB0k02IwNcfRmg_9jBA
16:35:22 | Download completed, processing action action=download name=debian-13.6.0-amd64-netinst.iso
16:35:22 | Downloading 0 files...
16:35:22 | ERROR Error running post-download action error="no valid download links available for debian-13.6.0-amd64-netinst.iso"

Submitted-to-failed in ~3 seconds. A manual GET /api/item/details against
Premiumize's API for the same file a few minutes later (for a different,
similarly-affected torrent) returned a fully populated link/directlink,
virus_scan: "ok", correct size - i.e. genuinely ready, just not yet at the
moment processTorrentDownload looked.

Today this fails permanently and needs a manual re-add (which, for a torrent
already cached provider-side, just re-submits the same infohash and usually
works immediately, confirming it's a timing issue and not a bad source). The
existing repair worker can also catch this in the background if source: managed is configured, but that's a several-minutes-later mitigation, not a
fix for the immediate failure on first grab from an *arr.

Caveat

I don't have a Go toolchain available in the environment I wrote this in, so
this has not been compiled or run. I reviewed it by hand against the
current type definitions (ProviderEntry, ProviderFile, storage.File,
debrid/types.Torrent/File) and existing call sites for
GetActiveProvider/ProviderClient/GetTorrent elsewhere in the codebase,
but please build and test before merging - happy to fix up anything that
doesn't compile or behaves differently than intended.

Also open to a different shape entirely (e.g. hooking into the existing
repair/RunChecks machinery instead of a local retry loop) if that fits the
codebase's direction better - I went with the smallest, most self-contained
change I could reason about without a build.

Some debrid providers (Premiumize in particular) can flip a transfer's
status to "finished" before the file's actual download link has been
generated on their side. This is most noticeable for content that's
already cached and completes in well under a second - the very first
status check right after submission can race that window and see zero
files, even though the provider confirms a valid link for the same
file moments later.

Today this permanently fails the download with "no valid download
links available", for torrents that were, paradoxically, the fastest
and most available to fetch. Observed with Premiumize on already-cached
single-file torrents (software ISOs/installers): the transfer flips to
"finished" ~1s after submission, filesForTransfer sees no link yet, and
processTorrentDownload gives up immediately - while a manual query of
the provider's item details a few seconds later shows the file fully
ready with a working link.

This adds a short, bounded retry (5 attempts, 2s/4s/8s/16s/16s backoff,
~30s total) that re-fetches the torrent from its active provider when
GetActiveFiles() is empty, before giving up.

Caveat: I don't have a Go toolchain available in the environment I
wrote this in, so this has not been compiled or run - only reviewed
by hand against the current types (ProviderEntry, ProviderFile,
storage.File, debrid/types.Torrent/File) and the existing
GetActiveProvider/ProviderClient/GetTorrent call sites elsewhere in
the codebase. Please build/test before merging.
@BasterdOperator
BasterdOperator force-pushed the fix/instant-cache-empty-files branch from 1e1bd22 to 283402c Compare August 17, 2026 16:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant