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/main/java/org/elasticsearch/search/aggregations/support/AggregationPath.java
public Aggregator resolveTopmostAggregator(Aggregator root) {
        AggregationPath.PathElement token = pathElements.get(0);
        
        Aggregator aggregator = ProfilingAggregator.unwrap(root.subAggregator(token.name));
        assert (aggregator instanceof SingleBucketAggregator) || (aggregator instanceof NumericMetricsAggregator)
            : "this should be picked up before aggregation execution - on validate";
        return aggregator;
    }
    public BucketComparator bucketComparator(Aggregator root, SortOrder order) {
        return resolveAggregator(root).bucketComparator(Optional.ofNullable(lastPathElement().key).orElse(lastPathElement().metric), order);
    }
    private static String[] split(String toSplit, int index, String[] result) {
        result[0] = toSplit.substring(0, index);
        result[1] = toSplit.substring(index + 1);
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (obj == null || getClass() != obj.getClass()) {
            return false;
        }
        AggregationPath other = (AggregationPath) obj;
        return pathElements.equals(other.pathElements);
    }
    @Override
    public int hashCode() {
        return pathElements.hashCode();
    }
}