### Description

InternalComposite.formatObject() can throw an IllegalArgumentException if the format to be applied to a composite key leads to a loss of information (eg, a date histogram with a width of one day is then given a date format of 'YYYY-mm', meaning that multiple buckets from the same month would produce the same key).  This is currently only checked during serialization, meaning that we can do a great deal of work building aggregations only to then throw the result away at the end.  This also causes a problem for converting the `_search` endpoint to using chunked xcontent serialization, as the HTTP response code is the first thing sent back, and so errors that occur during later serialization don't get handled correctly.
server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/InternalComposite.java
long value = (long) obj;
            if (format == DocValueFormat.RAW) {
                formatted = value;
            } else {
                formatted = format.format(value);
            }
            parsed = format.parseLong(
                formatted.toString(),
                false,
                () -> { throw new UnsupportedOperationException("Using now() is not supported in after keys"); }
            );
            if (parsed.equals(((Number) obj).longValue()) == false) {
                throw new IllegalArgumentException(
                    "Format ["
                        + format
                        + "] created output it couldn't parse for value ["
                        + obj
                        + "] "
                        + "of type ["
                        + obj.getClass()
                        + "]. parsed value: ["
                        + parsed
                        + "("
                        + parsed.getClass()
                        + ")]"
                );
            }
        } else if (obj.getClass() == Double.class) {
            double value = (double) obj;
            if (format == DocValueFormat.RAW) {