elastic/elasticsearch · error · MustacheException
Mustache function [{}] must contain one and only one identif
Error message
Mustache function [{}] must contain one and only one identifier What it means
Thrown by CustomCode.extractVariableName() at compile time when a custom mustache function (toJson, join, url) contains zero or more than one inner code element. The function parsing expects exactly one identifier inside the function block, e.g., {{#toJson}}variable_name{{/toJson}}. If codes is null or codes.length != 1, the function cannot determine which variable to resolve.
Source
Thrown at modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/CustomMustacheFactory.java:193
@Override
protected void tag(Writer writer, String tag) throws IOException {
writer.write(tc.startChars());
writer.write(tag);
writer.write(code);
writer.write(tc.endChars());
}
protected abstract Function<String, String> createFunction(Object resolved);
/**
* At compile time, this function extracts the name of the variable:
* {{#toJson}}variable_name{{/toJson}}
*/
protected static String extractVariableName(String fn, Mustache mustache, TemplateContext tc) {
Code[] codes = mustache.getCodes();
if (codes == null || codes.length != 1) {
throw new MustacheException("Mustache function [" + fn + "] must contain one and only one identifier");
}
try (StringWriter capture = new StringWriter()) {
// Variable name is in plain text and has type WriteCode
if (codes[0] instanceof WriteCode) {
codes[0].execute(capture, List.of());
} else {
codes[0].identity(capture);
}
return capture.toString();
} catch (IOException e) {
throw new MustacheException("Exception while parsing mustache function [" + fn + "] at line " + tc.line(), e);
}
}
}
/**
* This function renders {@link Iterable} and {@link Map} as their JSON representationView on GitHub (pinned to db6a809a66)
Solutions
- Put exactly one variable name inside the function block: {{#toJson}}myvar{{/toJson}}
- If you need multiple values as JSON, pass them as a single array or map parameter: {{#toJson}}multi_value_param{{/toJson}} where the param is an array
- Ensure the block contains only the variable name with no extra whitespace-only or empty codes
- Use {{#join}}myvar{{/join}} (single variable that resolves to an Iterable) for delimiter joining
Example fix
// before — two variables inside toJson:
{{#toJson}}{{field1}}{{field2}}{{/toJson}}
// after — single variable (pass combined data as one param):
{{#toJson}}combined{{/toJson}}
// where 'combined' is provided as a Map or List in params Defensive patterns
Strategy: validation
Validate before calling
// Validate that custom function blocks contain exactly one identifier
// Parse template and check each {{#toJson}}, {{#join}}, {{#url}} block
// has exactly one variable reference inside Prevention
- Put exactly one variable name inside {{#toJson}}...{{/toJson}} and similar blocks
- Pass arrays/maps as a single param rather than multiple variables inside a function
- Keep function blocks minimal: {{#toJson}}singleVar{{/toJson}}
When it happens
Trigger: Writing a custom function block with no content, empty content, or multiple variables inside. Example: {{#toJson}}{{var1}}{{var2}}{{/toJson}} (two variables) or {{#toJson}}{{/toJson}} (empty). The mustache compiler produces a Code array from the block content, and extractVariableName checks its length at compile time.
Common situations: Putting multiple variables inside a {{#toJson}}...{{/toJson}} block expecting them to be merged into one JSON object. Leaving the function block empty. Nesting sections or conditionals inside a function block. Using complex expressions instead of a bare variable name.
Related errors
- Failed to convert object to JSON
- {ex.getMessage()}
- Unable to encode value
- No encoder found for media type [{}]
- Cannot expand '%s' because partial templates are not support
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/ac982d96788ecd37.
Report an issue: GitHub.