[BUG] Content Drive: failed/timed-out ES sub-queries silently return incomplete pages as HTTP 200
Related to #37184. Follow-up from #37395 (single-pass field filter resolution) — flagged in review but scoped out since it's pre-existing behavior, not introduced by that PR.
Problem
In dotCMS/src/main/java/com/dotcms/browser/BrowserAPIImpl.java:
processSingleESQuery catches every exception thrown by the ES search call, logs it, and returns an empty set instead of propagating the failure.
processMultipleESQueries (used when the inode set is split into several sub-queries) wraps each sub-query future with .orTimeout(60, SECONDS).exceptionally(...), which also returns an empty set per failed/timed-out sub-query. The outer allFutures.get(120, SECONDS) call additionally catches InterruptedException/ExecutionException/TimeoutException, logs them, and falls through without failing the request.
Net effect: a slow or failed ES sub-query silently drops its share of matches from the response. The caller still gets back HTTP 200 with a short/incomplete page — there is nothing in the response indicating that results are incomplete.
Why it matters now
This risk is not new, but it was narrow: historically there were only 1-2 ES sub-queries per Content Drive request, so the odds that any one of them failed or timed out in a given request were low. A related change widens the field-filter fan-out from 2 sub-queries to potentially dozens per request. With more sub-queries per invocation, the chance that at least one drops out per request rises accordingly. The symptom reported by users would be something like "my filter sometimes misses content," with no error or indication anywhere in the response.
Proposed fix direction
Change the swallow-and-continue behavior in processSingleESQuery / processMultipleESQueries so a sub-query failure propagates as a request-level failure (a visible error response) instead of silently substituting an empty result and returning a short page.
Care needed:
- Verify blast radius — check whether
hydrateContentletsInParallel / findContentletsInParallel or any other caller shares code paths with these two methods and might currently depend on the lenient (swallow-and-continue) behavior.
- Callers that don't hit this failure path should see no behavior change.
Acceptance criteria
[BUG] Content Drive: failed/timed-out ES sub-queries silently return incomplete pages as HTTP 200
Related to #37184. Follow-up from #37395 (single-pass field filter resolution) — flagged in review but scoped out since it's pre-existing behavior, not introduced by that PR.
Problem
In
dotCMS/src/main/java/com/dotcms/browser/BrowserAPIImpl.java:processSingleESQuerycatches every exception thrown by the ES search call, logs it, and returns an empty set instead of propagating the failure.processMultipleESQueries(used when the inode set is split into several sub-queries) wraps each sub-query future with.orTimeout(60, SECONDS).exceptionally(...), which also returns an empty set per failed/timed-out sub-query. The outerallFutures.get(120, SECONDS)call additionally catchesInterruptedException/ExecutionException/TimeoutException, logs them, and falls through without failing the request.Net effect: a slow or failed ES sub-query silently drops its share of matches from the response. The caller still gets back HTTP 200 with a short/incomplete page — there is nothing in the response indicating that results are incomplete.
Why it matters now
This risk is not new, but it was narrow: historically there were only 1-2 ES sub-queries per Content Drive request, so the odds that any one of them failed or timed out in a given request were low. A related change widens the field-filter fan-out from 2 sub-queries to potentially dozens per request. With more sub-queries per invocation, the chance that at least one drops out per request rises accordingly. The symptom reported by users would be something like "my filter sometimes misses content," with no error or indication anywhere in the response.
Proposed fix direction
Change the swallow-and-continue behavior in
processSingleESQuery/processMultipleESQueriesso a sub-query failure propagates as a request-level failure (a visible error response) instead of silently substituting an empty result and returning a short page.Care needed:
hydrateContentletsInParallel/findContentletsInParallelor any other caller shares code paths with these two methods and might currently depend on the lenient (swallow-and-continue) behavior.Acceptance criteria