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

  1. Read the inner exception message to identify the specific compilation error (partial unsupported, function parsing, syntax error, etc.)
  2. Validate mustache syntax: ensure all {{ }} tags are properly closed, sections {{#x}}...{{/x}} are balanced
  3. Remove unsupported features: partials ({{>}}), dynamic partials ({{$}}), and any mustache extensions not listed in Elasticsearch docs
  4. 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

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


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