Skip to content

[BUG] Content Drive: failed/timed-out ES sub-queries silently return incomplete pages as HTTP 200 #37488

Description

@ihoffmann-dot

[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

  • 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions