elastic/elasticsearch · error · MustacheException

Failed to convert object to JSON

Error message

Failed to convert object to JSON

What it means

Thrown by ToJsonCode.createFunction() when an IOException occurs while serializing a resolved parameter value to JSON using XContentBuilder. The toJson function attempts to render Iterables as JSON arrays and Maps as JSON objects; if the XContentBuilder encounters a serialization failure (e.g., an unserializable object type), it throws IOException which is wrapped in this MustacheException.

Source

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

                if (resolved == null) {
                    return null;
                }
                try (XContentBuilder builder = XContentBuilder.builder(XContentType.JSON.xContent())) {
                    if (resolved instanceof Iterable) {
                        builder.startArray();
                        for (Object o : (Iterable<?>) resolved) {
                            builder.value(o);
                        }
                        builder.endArray();
                    } else if (resolved instanceof Map) {
                        builder.map((Map<String, ?>) resolved);
                    } else {
                        // Do not handle as JSON
                        return oh.stringify(resolved);
                    }
                    return Strings.toString(builder);
                } catch (IOException e) {
                    throw new MustacheException("Failed to convert object to JSON", e);
                }
            };
        }

        static boolean match(String variable) {
            return CODE.equalsIgnoreCase(variable);
        }
    }

    /**
     * This function concatenates the values of an {@link Iterable} using a given delimiter
     */
    private static class JoinerCode extends CustomCode {

        protected static final String CODE = "join";
        private static final String DEFAULT_DELIMITER = ",";

        private final String delimiter;

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure the parameter passed to {{#toJson}} is a simple type (String, Number, Boolean), a List of simple types, or a Map with String keys and simple values
  2. Check the params object in the search template request for any custom or non-serializable types
  3. If passing a Map, ensure all keys are Strings and all values are JSON-compatible
  4. Test the parameter serialization independently with a JSON serializer to isolate the failing value

Example fix

// before — param with non-serializable nested object:
{"params": {"filter": {"geojson": <complex geojson object>}}}

// after — use simple types only:
{"params": {"filter": ["tag1", "tag2", "tag3"]}}
Defensive patterns

Strategy: validation

Validate before calling

// Validate params before using toJson — ensure JSON-serializable types
void validateParams(Map<String, Object> params) {
    for (var entry : params.entrySet()) {
        Object v = entry.getValue();
        if (!(v == null || v instanceof String || v instanceof Number || v instanceof Boolean
              || v instanceof List || v instanceof Map)) {
            throw new IllegalArgumentException("Param [" + entry.getKey() + "] is not JSON-serializable");
        }
    }
}

Type guard

boolean isJsonSerializable(Object o) {
    return o == null || o instanceof String || o instanceof Number
        || o instanceof Boolean || o instanceof List || o instanceof Map;
}

Prevention

When it happens

Trigger: Using {{#toJson}}var{{/toJson}} where 'var' resolves to an object that XContentBuilder cannot serialize. For example, a parameter value that is a custom Java type, a nested structure containing nulls in unexpected positions, or a type that falls through to oh.stringify() and fails. Also possible if the resolved value is neither Iterable nor Map but the object handler's stringify fails.

Common situations: Passing complex nested objects as template params where some leaf values are not JSON-serializable. Passing a parameter that is a Set or other non-List Iterable with elements that XContentBuilder rejects. Version mismatches where a parameter type changes between client and server.

Related errors


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