[BUG] Infinite pending-import retry recreates user-deleted authors as monitored and ignores ImportListExclusions
Maintainers usually reply within 7 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
Research direction
Start with src/NzbDrone.Core/Books/Commands/ProcessPendingImportsCommandHandler.cs, then read AuthorLibraryService.cs, PendingAuthorImportService.cs, and PendingAuthorImportRepository.cs at the paths named in the issue. Trace how exclusions, deleted authors, and unresolved requested works are handled, and compare exclusion matching with ImportListSyncService. Done means retries cannot resurrect excluded authors, removed lists do not leave orphaned retries, and work that cannot resolve can reach a terminal state.
Written by the indexing model from the issue text.
Description
Describe the bug
A PendingAuthorImport row whose requested works can never be resolved retries forever (MaxAttempts = 0, no terminal condition). Each retry calls AuthorLibraryService.AddAuthorAsync with the monitoring config stored on the row. If the user has since deleted the author, the retry re-inserts it monitored (both media sides) with MonitorNewItems = All.
Two things make this unrecoverable from the UI:
ImportListExclusionsis never consulted on the pending-queue path, so the exclusion that the UI creates on "delete author → add import list exclusion" does not stop the retry.- Removing the import list that queued the row does not purge or cancel its pending rows.
Observed in production: one row at 415 attempts over ~2 days, reinstating the author roughly every 5 minutes.
To Reproduce
-
Have a Hardcover import list whose request includes a work that the metadata server keeps out of the author's catalog (announced/upcoming work, or a work with no editions). The row never reaches the success path and is retried indefinitely with errors like:
Requested Ebook work hc:XXXXXX, Ebook work hc:YYYYYY is not yet present in the authoritative author catalog. Requested work(s) hc:ZZZZZZ ... are still being prepared by the metadata server. -
Let it retry.
AttemptCountclimbs without bound;OverallStatusstaysRetrying(3);MaxAttemptsstays0. -
Delete the imported author from the library, with "add import list exclusion" checked.
-
Observe: within ~5 minutes the author is re-added and monitored. The exclusion does not prevent it.
Expected behavior
- Retries should not resurrect an author the user deliberately deleted.
- An
ImportListExclusionfor the row's provider ID should stop, cancel, or refuse the retry. - Removing an import list should not leave permanently-retrying orphan rows behind.
- A row that cannot ever succeed should reach a terminal state instead of retrying forever.
Root cause (source, running develop @ e67374f)
src/NzbDrone.Core/Books/Commands/ProcessPendingImportsCommandHandler.cs
ProcessPendingImportAsync(line 198) callsAddAuthorAsync(item.ProviderId, config)(line 226) before any check on whether the requested works can be resolved.- When they can't be, it calls
_pendingImportService.ScheduleRetry(item, reason)(lines 254/270) and returns — the success path (MarkSucceededline 280 +TryDeleteIfUnchanged) is unreachable, so the row is immortal. - Nothing in this handler reads
ImportListExclusions.
src/NzbDrone.Core/Books/Services/AuthorLibraryService.cs
- Line 331:
ApplyMonitoringConfig(author, config)sets the media gates from the row's stored config before any existence check. - Line 351: if no author exists locally, the create path runs — line 389
_authorService.AddAuthor(author, false)inserts the recreated author with those gates applied. This is the resurrection. - Line 354: if the author does exist,
HandleExistingAuthorAsync→ line 1068ApplyExistingAuthorProgressiveSettings, which routes intoUpdateAuthorProgressiveSettings. That method does NULL-only fills (if (!author.AudiobookMonitored.HasValue && audiobookMonitored.HasValue)), so an author that was merely unmonitored keeps its explicitfalse— the damage is specifically on the delete-then-recreate path.
src/NzbDrone.Core/Books/Services/PendingAuthorImportService.cs
Cancel(int id)(line 677) exists and sets a terminal status, but nothing calls it automatically when an exclusion is added or a list is removed.
src/NzbDrone.Core/Books/Repositories/PendingAuthorImportRepository.cs
GetDueForProcessing(line 45) selects rows withOverallStatus == Pending || RetryingandNextAttemptAt <= cutoff— no attempt ceiling.
Evidence
Pending rows at time of filing (5 rows, all MaxAttempts = 0):
Id ProviderId OverallStatus AttemptCount LastError
103 hc:NNNNNN 3 (Retrying) 415 Requested Ebook work hc:XXXXXX, hc:YYYYYY is not yet present in the authoritative author catalog.
122 hc:NNNNNN 3 (Retrying) 96 Requested Ebook work hc:XXXXXX, hc:YYYYYY is not yet present in the authoritative author catalog.
117 hc:NNNNNN 3 (Retrying) 93 Requested Audiobook work hc:XXXXXX, hc:YYYYYY, Ebook work hc:XXXXXX is not yet present in the authoritative author catalog.
118 hc:NNNNNN 3 (Retrying) 95 Requested Ebook work hc:XXXXXX is not yet present in the authoritative author catalog.
119 hc:NNNNNN 3 (Retrying) 97 Requested work(s) hc:XXXXXX, hc:XXXXXX are still being prepared by the metadata server.
(provider/work IDs redacted; happy to supply on request)
Log, repeating every ~5 minutes indefinitely:
2026-09-29 01:17:53.5|Info|ProcessPendingImportsCommandHandler|Processing pending import 103 for provider hc:NNNNNN
2026-09-29 01:17:53.5|Info|ProcessPendingImportsCommandHandler|Processing queued author import for provider hc:NNNNNN
2026-09-29 01:17:54.8|Info|AuthorLibraryService|Author 'Author A' already exists in database with 45 books (audiobook=True, ebook=True)
...
2026-09-29 09:18:16.1|Info|AuthorLibraryService|Author 'Author A' already exists in database with 45 books (audiobook=True, ebook=True)
ImportListExclusions contains the correct exclusion for that provider ID, created via the delete-author flow. ImportLists is empty (list removed) — the pending rows survived.
Suggested fixes
- Honour
ImportListExclusionsinProcessPendingImportsCommandHandler(sameMatchesExclusionIdsemantics asImportListSyncService) — skip and cancel the row. - Cancel pending rows for an author when the user deletes it with "add import list exclusion", and/or when the queueing import list is removed.
- Do not re-apply
AudiobookMonitored/EbookMonitored/MonitorNewItemsfrom a stored row when the author already exists and the user has explicitly changed those settings — the manual-override flags (AudiobookSettingsManuallyOverridden/EbookSettingsManuallyOverridden) exist for exactly this and are not consulted here. - Give the "requested work not present in catalog" branch a terminal or long-backoff state (it can never resolve on its own). Related: #119 covers the unbounded-retry family.
Workaround
The supported cancel endpoint stops it, and the row then leaves the retry set (GetDueForProcessing only selects Pending/Retrying):
curl -X DELETE -H "X-Api-Key: $KEY" http://HOST:8789/api/v1/pendingauthorimport/103
# -> {"message": "Pending import cancelled"}
Finding the stuck rows requires GET /api/v1/pendingauthorimport. The API was the only path I found to list or cancel these rows once the author is absent from the library, which is why this is easy to hit and hard to diagnose.
System Information:
- OS: Ubuntu 24.04 (Docker container, Unraid host)
- Chaptarr Version: 0.9.965.0 (develop), migrationVersion 107
- Installation Method: Docker (
chaptarr/chaptarr:develop) - Database: PostgreSQL 18 (not SQLite — this is not the #119 lock cascade)
- Dominant language
- C#
- Stars
- 664
- Forks
- 48
- Avg merge
- 3d 5h
- Merged PRs (30d)
- 1
Getting set up
- Ships a Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from Chaptarr/chaptarr
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 7 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
Chaptarr/chaptarr#313 · 1 comment ·
Maintainers usually reply within 7 days
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 7 days
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 63/100
Maintainers usually reply within 7 days
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 7 days
All issues in Chaptarr/chaptarr
Similar issues
-
needs-triage
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Maintainers usually reply within 1 day
-
7.0
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
unoplatform/uno.extensions#3253 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Sector-Vestige/Sector-Vestige#476 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
PowerShell/platyPS#868 ·
-
S: Untriaged
Difficulty 2/5 1-3 hours Newbie friendliness 62/100
Trauma-Station/Trauma-Station#5058 ·
Maintainers usually reply within 1 day