Observed on 1.3.4 against an NZBGet instance that predates the Listenarr install and still carries its old failed history. NZBGet does not purge failed history on its own, so the backlog is permanent unless someone clears it by hand.
What the log looks like: millions of WRN lines over a few days, nearly all of them from NzbgetAdapter, with this shape:
NZBGet history reported failure for <id>: Status=FAILURE/PAR, FinalDir=[empty-path], DestDir=<...>, Title=<...>, Category=books, ClientId=<...>, Surface=GetQueueAsync
A few dozen distinct history IDs account for all of it. Each was logged on the order of tens of thousands of times, and the per-ID count is identical across all of them, which is the signature of one unconditional re-emit per poll rather than anything happening. The poll runs about every five seconds. The daily log files run to several hundred megabytes of this one message, and the set grows: IDs that were not in the earlier sample appeared within minutes of a container restart.
Joining those IDs against the Downloads table, only two of them were ever submitted by this Listenarr install. The rest have no Listenarr record at all. The adapter is scanning and re-reporting entries the application never claimed.
Reading canary a630572e, I think the path is NzbgetHistoryEnrichmentWorkflow.cs. The loop at :160-175 calls LogFailedHistoryEntry (:288) for every entry that passes IsHistoryCandidate (:180), and that filter only excludes entries outside the configured category, duplicates within the same response, and entries still matched by an active queue item. An old failed entry with no active match returns true at :207, so it is a candidate on every call. The processedHistoryIds set at :157 is local to the call, so nothing remembers across polls what has already been warned about. The warning itself came in with #599 (3b25386d), from the earlier commit "Fix NZBGet failed history handling" (39d39ae9), so it was added on purpose; I am not suggesting it goes, only that it fires once.
Two things I have not fully traced, in case they are the more interesting part:
- The two failures Listenarr did submit sat at the same
Downloads status with a null completion timestamp and no import attempts for the whole window, while NZBGet reported them failed on every poll, and neither became a blocked release. The failed-download path works in the common case on this install, since plenty of other entries went through it, so this looks like a gap rather than a break.
Downloads.HistoryId (Download.cs:119) is declared and is null on every row here; I could not find a writer for it in the source. The join above had to be made on title, which is an approximation. If that column were populated, the adapter could scope the history scan to its own entries and none of this would need title matching.
One thing that does not work as a stopgap, in case anyone else tries it: a per-category Serilog:MinimumLevel:Override in the external appsettings.json has no effect. ListenarrBuilderFactory.cs:162 reads only Serilog:MinimumLevel:Default from configuration, and the logger at :183-187 is built in code with a fixed set of overrides, so per-category overrides from the file are never applied. Restarted the container after adding one and the flood was unchanged.
PR #950 does the first two of these: it scopes the history scan during monitor polls to entries this install can attribute to itself, and it remembers per history ID and per surface that a failure has already been warned about, so an entry warns once per container start. On the install above, over a thirty-minute window from start on a build carrying it, the warning count went from tens of thousands to zero with both clients still polled at the same cadence. It leaves the third alone: why the two real failures never became blocks is a separate question, and I would rather it be looked at than guessed at.
Disclosure: drafted with Claude Code at my direction; the log and database reads above were done on a running install, and I read the cited code at the stated commit and reviewed this before posting.
Observed on 1.3.4 against an NZBGet instance that predates the Listenarr install and still carries its old failed history. NZBGet does not purge failed history on its own, so the backlog is permanent unless someone clears it by hand.
What the log looks like: millions of WRN lines over a few days, nearly all of them from
NzbgetAdapter, with this shape:A few dozen distinct history IDs account for all of it. Each was logged on the order of tens of thousands of times, and the per-ID count is identical across all of them, which is the signature of one unconditional re-emit per poll rather than anything happening. The poll runs about every five seconds. The daily log files run to several hundred megabytes of this one message, and the set grows: IDs that were not in the earlier sample appeared within minutes of a container restart.
Joining those IDs against the
Downloadstable, only two of them were ever submitted by this Listenarr install. The rest have no Listenarr record at all. The adapter is scanning and re-reporting entries the application never claimed.Reading canary
a630572e, I think the path isNzbgetHistoryEnrichmentWorkflow.cs. The loop at:160-175callsLogFailedHistoryEntry(:288) for every entry that passesIsHistoryCandidate(:180), and that filter only excludes entries outside the configured category, duplicates within the same response, and entries still matched by an active queue item. An old failed entry with no active match returns true at:207, so it is a candidate on every call. TheprocessedHistoryIdsset at:157is local to the call, so nothing remembers across polls what has already been warned about. The warning itself came in with #599 (3b25386d), from the earlier commit "Fix NZBGet failed history handling" (39d39ae9), so it was added on purpose; I am not suggesting it goes, only that it fires once.Two things I have not fully traced, in case they are the more interesting part:
Downloadsstatus with a null completion timestamp and no import attempts for the whole window, while NZBGet reported them failed on every poll, and neither became a blocked release. The failed-download path works in the common case on this install, since plenty of other entries went through it, so this looks like a gap rather than a break.Downloads.HistoryId(Download.cs:119) is declared and is null on every row here; I could not find a writer for it in the source. The join above had to be made on title, which is an approximation. If that column were populated, the adapter could scope the history scan to its own entries and none of this would need title matching.One thing that does not work as a stopgap, in case anyone else tries it: a per-category
Serilog:MinimumLevel:Overridein the externalappsettings.jsonhas no effect.ListenarrBuilderFactory.cs:162reads onlySerilog:MinimumLevel:Defaultfrom configuration, and the logger at:183-187is built in code with a fixed set of overrides, so per-category overrides from the file are never applied. Restarted the container after adding one and the flood was unchanged.PR #950 does the first two of these: it scopes the history scan during monitor polls to entries this install can attribute to itself, and it remembers per history ID and per surface that a failure has already been warned about, so an entry warns once per container start. On the install above, over a thirty-minute window from start on a build carrying it, the warning count went from tens of thousands to zero with both clients still polled at the same cadence. It leaves the third alone: why the two real failures never became blocks is a separate question, and I would rather it be looked at than guessed at.
Disclosure: drafted with Claude Code at my direction; the log and database reads above were done on a running install, and I read the cited code at the stated commit and reviewed this before posting.