[BUG] Content Drive: failed/timed-out ES sub-queries silently return incomplete pages as HTTP 200
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
[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 / 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/findContentletsInParallelor 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
- A sub-query failure or timeout causes the overall request to fail with a clear error, instead of silently returning a short HTTP 200 page.
- Existing callers that never hit an ES sub-query failure see no behavior change.
- Test coverage: a test that forces one sub-query to throw or time out (via a mocked/injected failure) and asserts the overall request surfaces an error rather than a partial success.
Contributor 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.
Research direction
Start in dotCMS/src/main/java/com/dotcms/browser/BrowserAPIImpl.java by tracing processSingleESQuery and processMultipleESQueries, including their timeout and exception handling. Check hydrateContentletsInParallel and findContentletsInParallel for shared callers and existing behavior. Add coverage that forces one sub-query to fail or time out and verifies the request returns an error rather than a partial HTTP 200 response.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- elasticsearch, java
- Domain
- backend, search
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100