### 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/test/java/org/elasticsearch/search/aggregations/bucket/composite/InternalCompositeTests.java
public void testReduceUnmapped() throws IOException {
        var mapped = createTestInstance(randomAlphaOfLength(10), emptyMap(), InternalAggregations.EMPTY);
        var rawFormats = formats.stream().map(f -> DocValueFormat.RAW).collect(toList());
        var unmapped = new InternalComposite(
            mapped.getName(),
            mapped.getSize(),
            sourceNames,
            rawFormats,
            emptyList(),
            null,
            reverseMuls,
            missingOrders,
            true,
            emptyMap()
        );
        List<InternalAggregation> toReduce = Arrays.asList(unmapped, mapped);
        Collections.shuffle(toReduce, random());
        InternalComposite finalReduce = (InternalComposite) unmapped.reduce(toReduce, emptyReduceContextBuilder().forFinalReduction());
        assertThat(finalReduce.getBuckets().size(), equalTo(mapped.getBuckets().size()));
        if (false == mapped.getBuckets().isEmpty()) {
            assertThat(finalReduce.getFormats(), equalTo(mapped.getFormats()));
        }
        var expectedIt = mapped.getBuckets().iterator();
        for (var bucket : finalReduce.getBuckets()) {
            InternalComposite.InternalBucket expectedBucket = expectedIt.next();
            assertThat(bucket.getRawKey(), equalTo(expectedBucket.getRawKey()));
            assertThat(bucket.getDocCount(), equalTo(expectedBucket.getDocCount()));
            assertThat(bucket.getFormats(), equalTo(expectedBucket.getFormats()));
        }
    }