{"record":{"id":"54aa13ae7d3a067f","repo":"elastic/elasticsearch","slug":"rest-total-hits-as-int-cannot-be-used-if-the-tra","errorCode":null,"errorMessage":"[rest_total_hits_as_int] cannot be used if the tracking of total hits is not accurate, got {trackTotalHitsUpTo}","messagePattern":"\\[rest_total_hits_as_int\\] cannot be used if the tracking of total hits is not accurate, got (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/TransportSearchTemplateAction.java","lineNumber":170,"sourceCode":"        builder.profile(searchTemplateRequest.isProfile());\n        checkRestTotalHitsAsInt(searchRequest, builder);\n        searchRequest.source(builder);\n        return searchRequest;\n    }\n\n    private static void checkRestTotalHitsAsInt(SearchRequest searchRequest, SearchSourceBuilder searchSourceBuilder) {\n        if (searchRequest.source() == null) {\n            searchRequest.source(new SearchSourceBuilder());\n        }\n        Integer trackTotalHitsUpTo = searchRequest.source().trackTotalHitsUpTo();\n        // trackTotalHitsUpTo is set to Integer.MAX_VALUE when `rest_total_hits_as_int` is true\n        if (trackTotalHitsUpTo != null) {\n            if (searchSourceBuilder.trackTotalHitsUpTo() == null) {\n                // trackTotalHitsUpTo should be set here, ensure that we can get an accurate total hits count\n                searchSourceBuilder.trackTotalHitsUpTo(trackTotalHitsUpTo);\n            } else if (searchSourceBuilder.trackTotalHitsUpTo() != SearchContext.TRACK_TOTAL_HITS_ACCURATE\n                && searchSourceBuilder.trackTotalHitsUpTo() != SearchContext.TRACK_TOTAL_HITS_DISABLED) {\n                    throw new IllegalArgumentException(\n                        \"[\"\n                            + RestSearchAction.TOTAL_HITS_AS_INT_PARAM\n                            + \"] cannot be used \"\n                            + \"if the tracking of total hits is not accurate, got \"\n                            + searchSourceBuilder.trackTotalHitsUpTo()\n                    );\n                }\n        }\n    }\n}\n","sourceCodeStart":152,"sourceCodeEnd":181,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/TransportSearchTemplateAction.java#L152-L181","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Drop the conflicting track_total_hits cap from the template body, or set it to true (accurate) when using rest_total_hits_as_int.","Remove the rest_total_hits_as_int param/setting if a finite cap on total hits is required for performance.","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.","Audit params passed to the template for any that inject a numeric track_total_hits value."],"exampleFix":"// before\nPOST /_search/template?rest_total_hits_as_int=true\n{\"id\":\"t\",\"params\":{\"cap\":100}}\n// template contains: \"track_total_hits\": {{cap}}\n// after\nPOST /_search/template?rest_total_hits_as_int=true\n{\"id\":\"t\",\"params\":{}}\n// template contains: \"track_total_hits\": true","handlingStrategy":"validation","validationCode":"// Before calling _search/template with rest_total_hits_as_int, ensure no finite track_total_hits cap\nfunction compatibleWithTotalHitsAsInt(templateSource, params) {\n  // Render the template (naive) and check the resulting source\n  const rendered = renderTemplate(templateSource, params);\n  const tth = rendered.match(/\"track_total_hits\"\\s*:\\s*(\\d+)/);\n  if (tth && Number(tth[1]) >= 0) {\n    throw new Error('rest_total_hits_as_int requires track_total_hits be true/-1 or absent; got ' + tth[1]);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never combine rest_total_hits_as_int with a numeric track_total_hits in the same request.","Centralize track_total_hits logic so params can't inject conflicting values.","Test templates with and without the int flag."],"tags":["search-template","mustache","search","track-total-hits","request-validation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}