### 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
this.formats = formats;
        this.buckets = buckets;
        this.afterKey = afterKey;
        this.size = size;
        this.reverseMuls = reverseMuls;
        this.missingOrders = missingOrders;
        this.earlyTerminated = earlyTerminated;
    }
    public InternalComposite(StreamInput in) throws IOException {
        super(in);
        this.size = in.readVInt();
        this.sourceNames = in.readStringList();
        this.formats = new ArrayList<>(sourceNames.size());
        for (int i = 0; i < sourceNames.size(); i++) {
            formats.add(in.readNamedWriteable(DocValueFormat.class));
        }
        this.reverseMuls = in.readIntArray();
        if (in.getTransportVersion().onOrAfter(TransportVersion.V_7_16_0)) {
            this.missingOrders = in.readArray(MissingOrder::readFromStream, MissingOrder[]::new);
        } else {
            this.missingOrders = new MissingOrder[reverseMuls.length];
            Arrays.fill(missingOrders, MissingOrder.DEFAULT);
        }
        this.buckets = in.readList((input) -> new InternalBucket(input, sourceNames, formats, reverseMuls, missingOrders));
        this.afterKey = in.readOptionalWriteable(CompositeKey::new);
        this.earlyTerminated = in.getTransportVersion().onOrAfter(TransportVersion.V_7_6_0) ? in.readBoolean() : false;
    }
    @Override
    protected void doWriteTo(StreamOutput out) throws IOException {
        out.writeVInt(size);