When parsing `AggregationPath` strings, if we hit an error, we throw `AggregationExecutionException`, which is a 500 class error.  But 500 class errors usually mean that retrying the request might improve the situation, where in this case we want to indicate that the user should not retry with the same request (they need to fix the path expression).  
server/src/test/java/org/elasticsearch/search/aggregations/support/AggregationPathTests.java
public void testInvalidPaths() {
        assertInvalidPath("[foo]", "brackets at the beginning of the token expression");
        assertInvalidPath("foo[bar", "open brackets without closing at the token expression");
        assertInvalidPath("foo[", "open bracket at the end of the token expression");
        assertInvalidPath("foo[]", "empty brackets in the token expression");
        assertInvalidPath("foo[bar]baz", "brackets not enclosing at the end of the token expression");
        assertInvalidPath(".foo", "dot separator at the beginning of the token expression");
        assertInvalidPath("foo.", "dot separator at the end of the token expression");
    }
    public void testValidPaths() {
        assertValidPath("foo[bar]._count", tokens().addKeyAndMetric("foo", "bar", "_count"));
        assertValidPath("foo>bar", tokens().add("foo").add("bar"));
        assertValidPath("foo.bar", tokens().addMetric("foo", "bar"));
        assertValidPath("foo[bar]", tokens().addKey("foo", "bar"));
        assertValidPath("foo[bar]>baz", tokens().addKey("foo", "bar").add("baz"));
        assertValidPath("foo[bar]>baz[qux]", tokens().addKey("foo", "bar").addKey("baz", "qux"));
        assertValidPath("foo[bar]>baz.qux", tokens().addKey("foo", "bar").addMetric("baz", "qux"));
        assertValidPath("foo.bar>baz.qux", tokens().add("foo.bar").addMetric("baz", "qux"));
        assertValidPath("foo.bar>baz[qux]", tokens().add("foo.bar").addKey("baz", "qux"));
    }
    private AggregationExecutionException assertInvalidPath(String path, String _unused) {
        return expectThrows(AggregationExecutionException.class, () -> AggregationPath.parse(path));
    }
    private void assertValidPath(String path, Tokens tokenz) {
        AggregationPath.PathElement[] tokens = tokenz.toArray();
        AggregationPath p = AggregationPath.parse(path);
        assertThat(p.getPathElements().size(), equalTo(tokens.length));
        for (int i = 0; i < p.getPathElements().size(); i++) {
            AggregationPath.PathElement t1 = p.getPathElements().get(i);
            AggregationPath.PathElement t2 = tokens[i];