elastic/elasticsearch · error · MustacheException

Unable to encode value

Error message

Unable to encode value

What it means

Thrown by CustomMustacheFactory.encode() when the configured encoder fails to write an encoded value due to an IOException. This is a low-level wrapper that catches I/O failures from the underlying Writer during template rendering and converts them into a MustacheException. The encoder itself (JsonEscapeEncoder, UrlEncoder, or DefaultEncoder) does not typically throw, so the IOException usually originates from the downstream Writer being closed or the output stream failing.

Source

Thrown at modules/lang-mustache/src/main/java/org/elasticsearch/script/mustache/CustomMustacheFactory.java:99

     * @deprecated Use {@link #builder()} instead to retrieve a {@link Builder} object that can be used to create a factory.
     */
    @Deprecated
    public CustomMustacheFactory() {
        this(DEFAULT_MEDIA_TYPE, DEFAULT_DETECT_MISSING_PARAMS);
    }

    private CustomMustacheFactory(String mediaType, boolean detectMissingParams) {
        super(resourceName -> null); // we do not resolve templates via files or the classpath, etc.
        setObjectHandler(new CustomReflectionObjectHandler(detectMissingParams));
        this.encoder = createEncoder(mediaType);
    }

    @Override
    public void encode(String value, Writer writer) {
        try {
            encoder.encode(value, writer);
        } catch (IOException e) {
            throw new MustacheException("Unable to encode value", e);
        }
    }

    static Encoder createEncoder(String mediaType) {
        final Supplier<Encoder> supplier = ENCODERS.get(mediaType);
        if (supplier == null) {
            throw new IllegalArgumentException("No encoder found for media type [" + mediaType + "]");
        }
        return supplier.get();
    }

    @Override
    public MustacheVisitor createMustacheVisitor() {
        return new CustomMustacheVisitor(this);
    }

    public static Builder builder() {
        return new Builder();

View on GitHub (pinned to db6a809a66)

Solutions

  1. Check for size-limit issues first — if mustache.max_output_size_bytes is being hit, the root cause is the size limit, not encoding
  2. Simplify the template to reduce output volume and retry
  3. Check server logs for concurrent OOM or stream-closed errors that could explain the I/O failure
  4. If reproducible, isolate the template parameter values that trigger the error and test them individually
Defensive patterns

Strategy: try-catch

Try / catch

// When executing templates programmatically, catch MustacheException
try {
    TemplateScript.Factory factory = engine.compile(...);
    String result = factory.newInstance(params).execute();
} catch (MustacheException e) {
    // check cause for IOException — often a secondary symptom
    log.warn("Template encoding failed: {}", e.getMessage());
}

Prevention

When it happens

Trigger: Executing a search template (via _search/template or _msearch/template) where template rendering writes to a Writer that encounters an I/O error mid-encode. This can happen when the output buffer is closed prematurely, when the SizeLimitingStringWriter has already thrown, or under memory pressure causing stream failures.

Common situations: Template execution under memory pressure or after a size-limit violation has partially corrupted the writer state. Concurrent use of a shared factory in a way that stresses I/O paths. Rarely seen in normal operation — usually a secondary symptom of another failing condition.

Related errors


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