You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Sibling of the case fixed in #755, filed separately because #640's design cares rule out the obvious fix.
The wedge
DownloadDuplicateGuard.HasActiveDownloadAsync treats ImportPending as active, so it blocks any re-grab of that audiobook (the API surfaces this as 409 "already active"). But DownloadOrphanCleanupService.GetCleanupReason only reconciles Queued/Downloading/Paused — deliberately, per #640: terminalizing ImportPending on a flaky snapshot would destroy pending imports.
The result: a download that completed in the client but whose files/queue item were removed before import (user deleted the finished torrent, seedbox cleanup, client history pruned) sits in ImportPending permanently. It blocks every future grab of that book and is invisible to the only mechanism that could clear it. Nothing self-heals; the user has to find the stale record in Activity and remove it by hand, with no hint from the 409 that this is the fix.
Possible directions (deliberately not a PR, since #640 constrains the design)
Make the duplicate guard snapshot-aware instead of terminalizing: an ImportPending row whose external id is absent from a live snapshot (and has no active import job) stops counting as "active" for duplicate-guard purposes, without touching its state. No mass-terminalization risk; the record stays for manual review.
On-demand reconcile before rejecting: when a grab is about to 409, run a scoped orphan check for that audiobook's client and only reject if the item is genuinely live in the client.
At minimum, make the 409 actionable: include the stale download id and a hint ("remove it from Activity to re-grab") or offer a "remove stale and retry" affordance.
Happy to implement whichever direction maintainers prefer.
Sibling of the case fixed in #755, filed separately because #640's design cares rule out the obvious fix.
The wedge
DownloadDuplicateGuard.HasActiveDownloadAsynctreatsImportPendingas active, so it blocks any re-grab of that audiobook (the API surfaces this as 409 "already active"). ButDownloadOrphanCleanupService.GetCleanupReasononly reconcilesQueued/Downloading/Paused— deliberately, per #640: terminalizingImportPendingon a flaky snapshot would destroy pending imports.The result: a download that completed in the client but whose files/queue item were removed before import (user deleted the finished torrent, seedbox cleanup, client history pruned) sits in
ImportPendingpermanently. It blocks every future grab of that book and is invisible to the only mechanism that could clear it. Nothing self-heals; the user has to find the stale record in Activity and remove it by hand, with no hint from the 409 that this is the fix.Possible directions (deliberately not a PR, since #640 constrains the design)
ImportPendingrow whose external id is absent from a live snapshot (and has no active import job) stops counting as "active" for duplicate-guard purposes, without touching its state. No mass-terminalization risk; the record stays for manual review.ImportPendingonly after continuous absence across N live snapshots plus a longer grace window (the Two cleanup paths never wired up: unbounded DownloadProcessingJobs; orphaned downloads never terminalized #640 "missing-since, not StartedAt" idea).Happy to implement whichever direction maintainers prefer.
🤖 Generated with Claude Code