elastic/elasticsearch · error · ScriptException
{ex.getMessage()}
Error message
{ex.getMessage()} What it means
Thrown by MustacheScriptEngine.compile() when a MustacheException is caught during template compilation. The original MustacheException message is preserved and wrapped in a ScriptException with the template source and engine name ('mustache'). This is the top-level compilation error handler — any syntax error, unsupported feature, or parsing failure in the mustache template surfaces here.
Source
Thrown at modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/MustacheScriptEngine.java:90
* Compile a template string to (in this case) a Mustache object than can
* later be re-used for execution to fill in missing parameter values.
*
* @param templateSource a string representing the template to compile.
* @return a compiled template object for later execution.
* */
@Override
public <T> T compile(String templateName, String templateSource, ScriptContext<T> context, Map<String, String> options) {
if (context.instanceClazz.equals(TemplateScript.class) == false) {
throw new IllegalArgumentException("mustache engine does not know how to handle context [" + context.name + "]");
}
final MustacheFactory factory = createMustacheFactory(options);
Reader reader = new StringReader(templateSource);
try {
Mustache template = factory.compile(reader, "query-template");
TemplateScript.Factory compiled = params -> new MustacheExecutableScript(template, params);
return context.factoryClazz.cast(compiled);
} catch (MustacheException ex) {
throw new ScriptException(ex.getMessage(), ex, List.of(), templateSource, NAME);
}
}
@Override
public Set<ScriptContext<?>> getSupportedContexts() {
return Set.of(TemplateScript.CONTEXT, TemplateScript.INGEST_CONTEXT);
}
private static CustomMustacheFactory createMustacheFactory(Map<String, String> options) {
CustomMustacheFactory.Builder builder = CustomMustacheFactory.builder();
if (options == null || options.isEmpty()) {
return builder.build();
}
if (options.containsKey(Script.CONTENT_TYPE_OPTION)) {
builder.mediaType(options.get(Script.CONTENT_TYPE_OPTION));
}View on GitHub (pinned to db6a809a66)
Solutions
- Read the inner exception message to identify the specific compilation error (partial unsupported, function parsing, syntax error, etc.)
- Validate mustache syntax: ensure all {{ }} tags are properly closed, sections {{#x}}...{{/x}} are balanced
- Remove unsupported features: partials ({{>}}), dynamic partials ({{$}}), and any mustache extensions not listed in Elasticsearch docs
- Test the template with a standalone mustache validator before sending to Elasticsearch
Example fix
// before — unclosed section tag:
{"query": {"bool": {"must": {{#filters}}{"term": {"x": "{{.}}"}}{{/filters}} ]}}
// after — properly balanced and valid:
{"query": {"bool": {"must": [{{#filters}}{"term": {"x": "{{.}}"}}{{/filters}}]}}} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate template syntax before sending to Elasticsearch
// Use a local mustache parser to check syntax, or use a regex-based pre-check
// for common errors: unclosed tags, unbalanced sections
boolean isBalanced(String src) {
int depth = 0;
Pattern p = Pattern.compile("\\{\{(#|/)([^}]+)\}\}");
Matcher m = p.matcher(src);
while (m.find()) {
depth += m.group(1).equals("#") ? 1 : -1;
}
return depth == 0;
} Try / catch
// Catch ScriptException when compiling templates
try {
engine.compile(templateName, templateSource, context, options);
} catch (ScriptException e) {
// e.getMessage() contains the original mustache error
throw new IllegalArgumentException("Template compilation failed: " + e.getMessage(), e);
} Prevention
- Validate mustache syntax before deploying templates
- Ensure all {{ }} tags are closed and sections are balanced
- Avoid unsupported features: partials, dynamic partials
- Store and test templates in a dev environment before production use
When it happens
Trigger: Compiling a search template that contains mustache syntax errors or uses unsupported features. The underlying MustacheException could be from partial/dynamic-partial usage (errors 1246/1247), function parsing failures (1248), or any other mustache parser error. The compile() method catches all MustacheException instances and converts them to ScriptException for consistent error reporting.
Common situations: Syntax errors like unclosed tags {{var without }}, mismatched section blocks {{#x}} without {{/x}}, using unsupported partial syntax, or malformed function calls. The actual root cause is in the wrapped exception — read ex.getMessage() to identify the specific compilation failure.
Related errors
- Mustache function [{}] must contain one and only one identif
- Unable to encode value
- No encoder found for media type [{}]
- Cannot expand '%s' because partial templates are not support
- Cannot expand '%s' because dynamic partial templates are not
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/2527ea9ccedaee92.
Report an issue: GitHub.