Finding
The CancellationToken branch in fetch_xml returns SearchIndexerError::ParseResponse with the message "request cancelled" in both TorznabClient and NewznabClient. In handle_search_error, the ParseResponse variant maps to the "degraded" indexer status, because it is treated as evidence the indexer returned malformed XML. A request cancelled by the caller (handler timeout, aborted query) is therefore indistinguishable from a parse failure and permanently marks every in-flight indexer as degraded even though all of them are healthy.
Evidence
crates/zetesis/src/client/torznab.rs:53-59:
() = ct.cancelled() => {
return Err(SearchIndexerError::ParseResponse {
url: url.to_string(),
error: "request cancelled".to_string(),
…
});
}
Identical cancellation branch at crates/zetesis/src/client/newznab.rs:53-59.
crates/zetesis/src/search.rs:230 maps the variant to a status change:
SearchIndexerError::ParseResponse { .. } => Some("degraded"),
Why this matters
Under the counter-surveillance threat model, the search subsystem is the operator's primary tooling and its availability matters. A single cancelled search silently degrades every indexer that was mid-request. An adversary able to induce cancellations (network-level disruption that trips the handler timeout) can disable the operator's entire indexer set without compromising any indexer, and the operator sees only mysteriously failing searches with no actionable error. Repeated frontend timeouts produce the same self-inflicted outage.
Desired correction
Add a dedicated SearchIndexerError::Cancelled variant (or reuse an existing variant that carries no status side-effect) and return it from the cancellation branch in both TorznabClient::fetch_xml and NewznabClient::fetch_xml. Add a matching arm in handle_search_error that maps Cancelled to None (no status update), and log the cancellation distinctly from a parse failure.
Done when: cancelling a request triggers no indexer status update, and the log line for a cancelled search is clearly distinguished from a parse failure.
Finding
The
CancellationTokenbranch infetch_xmlreturnsSearchIndexerError::ParseResponsewith the message"request cancelled"in bothTorznabClientandNewznabClient. Inhandle_search_error, theParseResponsevariant maps to the"degraded"indexer status, because it is treated as evidence the indexer returned malformed XML. A request cancelled by the caller (handler timeout, aborted query) is therefore indistinguishable from a parse failure and permanently marks every in-flight indexer as degraded even though all of them are healthy.Evidence
crates/zetesis/src/client/torznab.rs:53-59:Identical cancellation branch at
crates/zetesis/src/client/newznab.rs:53-59.crates/zetesis/src/search.rs:230maps the variant to a status change:Why this matters
Under the counter-surveillance threat model, the search subsystem is the operator's primary tooling and its availability matters. A single cancelled search silently degrades every indexer that was mid-request. An adversary able to induce cancellations (network-level disruption that trips the handler timeout) can disable the operator's entire indexer set without compromising any indexer, and the operator sees only mysteriously failing searches with no actionable error. Repeated frontend timeouts produce the same self-inflicted outage.
Desired correction
Add a dedicated
SearchIndexerError::Cancelledvariant (or reuse an existing variant that carries no status side-effect) and return it from the cancellation branch in bothTorznabClient::fetch_xmlandNewznabClient::fetch_xml. Add a matching arm inhandle_search_errorthat mapsCancelledtoNone(no status update), and log the cancellation distinctly from a parse failure.Done when: cancelling a request triggers no indexer status update, and the log line for a cancelled search is clearly distinguished from a parse failure.