elastic/elasticsearch · error · IllegalArgumentException

Unknown key for a VALUE_STRING in [project_routing]

Error message

Unknown key for a VALUE_STRING in [project_routing]

What it means

Thrown by the single _search/template REST handler when the request body includes a top-level 'project_routing' field but the cluster's cross-project search feature flag (crossProjectEnabled) is off. The field is only honored when the node is configured to allow cross-project routing; otherwise it is rejected as an unknown key rather than silently ignored.

Source

Thrown at modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/RestSearchTemplateAction.java:90

            request,
            null,
            clusterSupportsFeature,
            size -> searchRequest.source().size(size),
            null,
            Optional.of(crossProjectEnabled)
        );

        // Creates the search template request
        SearchTemplateRequest searchTemplateRequest;
        try (XContentParser parser = request.contentOrSourceParamParser()) {
            searchTemplateRequest = SearchTemplateRequest.fromXContent(parser);
        }

        if (searchTemplateRequest.getProjectRouting() != null) {
            if (crossProjectEnabled) {
                searchRequest.setProjectRouting(searchTemplateRequest.getProjectRouting());
            } else {
                throw new IllegalArgumentException("Unknown key for a VALUE_STRING in [project_routing]");
            }
        }

        searchTemplateRequest.setRequest(searchRequest);
        // This param is parsed within the search request
        if (searchRequest.source().explain() != null) {
            searchTemplateRequest.setExplain(searchRequest.source().explain());
        }
        return channel -> client.execute(
            MustachePlugin.SEARCH_TEMPLATE_ACTION,
            searchTemplateRequest,
            new RestRefCountedChunkedToXContentListener<>(channel) {
                @Override
                protected RestStatus getRestStatus(SearchTemplateResponse searchTemplateResponse) {
                    return searchTemplateResponse.status();
                }
            }
        );

View on GitHub (pinned to db6a809a66)

Solutions

  1. Remove the 'project_routing' key from the request body if cross-project routing is not needed.
  2. Enable the cross-project search feature on the cluster (set the governing node-level setting) and restart, if the deployment genuinely needs cross-project routing.
  3. Verify the Elasticsearch version supports this field and that the feature flag is actually toggled on via the cluster's settings API before sending.
  4. If routing is the intent, use the standard 'routing' parameter on the search request instead of 'project_routing'.

Example fix

// before
POST /_search/template
{ "id": "t", "params": {}, "project_routing": "projA" }
// after (cross-project disabled)
POST /_search/template
{ "id": "t", "params": {} }
Defensive patterns

Strategy: validation

Validate before calling

// Check feature availability before sending project_routing
async function canCrossProject(client) {
  // Probe cluster settings / feature flag relevant to your deployment
  const info = await client.info();
  // Heuristic: only attach project_routing when the deployment advertises cross-project support
  return Boolean(info.features && info.features.cross_project);
}
// then: if (!(await canCrossProject(client))) delete body.project_routing;

Try / catch

// ElasticsearchStatusException e -> if (e.getMessage().contains('project_routing')) { /* remove field and retry once */ }

Prevention

When it happens

Trigger: POST to _search/template (or _msearch/template) with a JSON body containing "project_routing": "value" while the controlling setting/flag for cross-project search is false (default). The handler checks searchTemplateRequest.getProjectRouting() != null && !crossProjectEnabled and throws.

Common situations: Enabling a feature in a client library or UI that targets a newer Elasticsearch version than the deployed cluster. Sending requests meant for a stateless/cross-project deployment to a standard cluster. Misreading docs that describe project_routing without noting the feature flag dependency.

Related errors


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