elastic/elasticsearch · error · IllegalArgumentException

[rest_total_hits_as_int] cannot be used if the tracking of t

Error message

[rest_total_hits_as_int] cannot be used if the tracking of total hits is not accurate, got {trackTotalHitsUpTo}

What it means

TransportSearchTemplateAction.checkRestTotalHitsAsInt enforces that when 'rest_total_hits_as_int' is requested (which internally sets trackTotalHitsUpTo to Integer.MAX_VALUE for accuracy), the rendered template's SearchSourceBuilder must either leave trackTotalHitsUpTo unset (so it can be forced accurate) or set it to ACCURATE (-1) or DISABLED. Any other positive cap is incompatible with returning total hits as an integer and is rejected.

Source

Thrown at modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/TransportSearchTemplateAction.java:170

        builder.profile(searchTemplateRequest.isProfile());
        checkRestTotalHitsAsInt(searchRequest, builder);
        searchRequest.source(builder);
        return searchRequest;
    }

    private static void checkRestTotalHitsAsInt(SearchRequest searchRequest, SearchSourceBuilder searchSourceBuilder) {
        if (searchRequest.source() == null) {
            searchRequest.source(new SearchSourceBuilder());
        }
        Integer trackTotalHitsUpTo = searchRequest.source().trackTotalHitsUpTo();
        // trackTotalHitsUpTo is set to Integer.MAX_VALUE when `rest_total_hits_as_int` is true
        if (trackTotalHitsUpTo != null) {
            if (searchSourceBuilder.trackTotalHitsUpTo() == null) {
                // trackTotalHitsUpTo should be set here, ensure that we can get an accurate total hits count
                searchSourceBuilder.trackTotalHitsUpTo(trackTotalHitsUpTo);
            } else if (searchSourceBuilder.trackTotalHitsUpTo() != SearchContext.TRACK_TOTAL_HITS_ACCURATE
                && searchSourceBuilder.trackTotalHitsUpTo() != SearchContext.TRACK_TOTAL_HITS_DISABLED) {
                    throw new IllegalArgumentException(
                        "["
                            + RestSearchAction.TOTAL_HITS_AS_INT_PARAM
                            + "] cannot be used "
                            + "if the tracking of total hits is not accurate, got "
                            + searchSourceBuilder.trackTotalHitsUpTo()
                    );
                }
        }
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Drop the conflicting track_total_hits cap from the template body, or set it to true (accurate) when using rest_total_hits_as_int.
  2. Remove the rest_total_hits_as_int param/setting if a finite cap on total hits is required for performance.
  3. If you need both capping and integer totals, set track_total_hits to -1 (accurate) so the check passes; the cap will not apply but totals will be exact.
  4. Audit params passed to the template for any that inject a numeric track_total_hits value.

Example fix

// before
POST /_search/template?rest_total_hits_as_int=true
{"id":"t","params":{"cap":100}}
// template contains: "track_total_hits": {{cap}}
// after
POST /_search/template?rest_total_hits_as_int=true
{"id":"t","params":{}}
// template contains: "track_total_hits": true
Defensive patterns

Strategy: validation

Validate before calling

// Before calling _search/template with rest_total_hits_as_int, ensure no finite track_total_hits cap
function compatibleWithTotalHitsAsInt(templateSource, params) {
  // Render the template (naive) and check the resulting source
  const rendered = renderTemplate(templateSource, params);
  const tth = rendered.match(/"track_total_hits"\s*:\s*(\d+)/);
  if (tth && Number(tth[1]) >= 0) {
    throw new Error('rest_total_hits_as_int requires track_total_hits be true/-1 or absent; got ' + tth[1]);
  }
}

Prevention

When it happens

Trigger: Calling _search/template with rest_total_hits_as_int=true (URI param or the setting that maps to it) while the template or params produce a SearchSourceBuilder where trackTotalHitsUpTo is a finite non-negative value other than the accurate/disabled sentinels — e.g. the template sets "track_total_hits": 100.

Common situations: Templates authored for paginated UIs that cap total hits for performance, then called with the int-serialization shortcut. Migrating a search to use rest_total_hits_as_int without auditing the source builder. Combining a profile/explain flow that injects a track_total_hits cap.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/54aa13ae7d3a067f. Report an issue: GitHub.