elastic/elasticsearch · error · IllegalArgumentException

project_routing already set

Error message

project_routing already set

What it means

Thrown by MultiSearchTemplateRequest.setProjectRouting() when the method is called more than once. The project_routing field is initialized to null and setProjectRouting checks if it is already non-null before assigning. This prevents accidental double-setting, which could occur if project_routing is specified both as a URL query parameter and elsewhere in the request processing pipeline.

Source

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

        for (SearchTemplateRequest templateRequest : multiSearchTemplateRequest.requests()) {
            final SearchRequest searchRequest = templateRequest.getRequest();
            try (XContentBuilder xContentBuilder = XContentBuilder.builder(xContent)) {
                MultiSearchRequest.writeSearchRequestParams(searchRequest, xContentBuilder);
                BytesReference.bytes(xContentBuilder).writeTo(output);
            }
            output.write(xContent.bulkSeparator());
            try (XContentBuilder xContentBuilder = XContentBuilder.builder(xContent)) {
                templateRequest.toXContent(xContentBuilder, ToXContent.EMPTY_PARAMS);
                BytesReference.bytes(xContentBuilder).writeTo(output);
            }
            output.write(xContent.bulkSeparator());
        }
        return output.toByteArray();
    }

    public void setProjectRouting(@Nullable String projectRouting) {
        if (this.projectRouting != null) {
            throw new IllegalArgumentException("project_routing already set");
        }

        this.projectRouting = projectRouting;
    }

    @Nullable
    public String getProjectRouting() {
        return projectRouting;
    }

}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Set project_routing only once per request — typically via the URL query parameter ?project_routing=<value>
  2. Check if project_routing is already set before calling setProjectRouting: if (request.getProjectRouting() == null) request.setProjectRouting(value)
  3. If using cross-project mode, ensure only one code path sets the routing
  4. Review client code to avoid duplicate setter calls

Example fix

// before — double set:
request.setProjectRouting("project-a");
request.setProjectRouting("project-b"); // throws

// after — guard or set once:
if (request.getProjectRouting() == null) {
    request.setProjectRouting("project-a");
}
Defensive patterns

Strategy: validation

Validate before calling

// Guard against double-setting project_routing
public void safeSetProjectRouting(MultiSearchTemplateRequest req, String routing) {
    if (req.getProjectRouting() != null) {
        throw new IllegalStateException("project_routing already set to: " + req.getProjectRouting());
    }
    req.setProjectRouting(routing);
}

Prevention

When it happens

Trigger: Calling setProjectRouting() twice on the same MultiSearchTemplateRequest instance. In practice, this can happen when the RestMultiSearchTemplateAction.parseRequest() method sets project_routing from the rest request parameter (line 81) and then another code path attempts to set it again. This is more likely in cross-project (Serverless) mode where project_routing handling is active.

Common situations: Cross-project search is enabled and project_routing is set from multiple sources (e.g., both URL param and internal pipeline). A bug in request processing that calls setProjectRouting twice. Using the API programmatically and accidentally calling the setter more than once.

Related errors


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