### Elasticsearch Version

8.11.1

### Installed Plugins

_No response_

### Java Version

_bundled_

### OS Version

N/A (Elastic Cloud)

### Problem Description

`_cluster/stats` returns a NullPointerException when there is an index with a dense_vector without dims, which is allowed as reported in the [documentation of the dense_vector type](https://www.elastic.co/guide/en/elasticsearch/reference/current/dense-vector.html). 
This endpoint is also used by Elastic-Agent/Metricbeat to gather cluster statistics and this bug can cause them not to work.

### Steps to Reproduce

Create a new index with the following mapping:
```
PUT breaking-cluster-stats
{
  "mappings": {
    "properties": {
      "foo": {
        "type": "dense_vector"
      }
    }
  }
}
```

Execute `_cluster/stats`. It will return:

```
{
  "error": {
    "root_cause": [
      {
        "type": "null_pointer_exception",
        "reason": "Cannot invoke \"java.lang.Integer.intValue()\" because the return value of \"java.util.Map.get(Object)\" is null"
      }
    ],
    "type": "null_pointer_exception",
    "reason": "Cannot invoke \"java.lang.Integer.intValue()\" because the return value of \"java.util.Map.get(Object)\" is null"
  },
  "status": 500
}
```

### Workaround

Create mapping with dims property or index a vector with the number of dimensions needed, e.g.: 
```
PUT breaking-cluster-stats/_doc/1 
{
  "foo": [1,1,1,1,...,1]
}
```

### Logs (if relevant)

Stack Trace:
> java.lang.NullPointerException: Cannot invoke "java.lang.Integer.intValue()" because the return value of "java.util.Map.get(Object)" is null at org.elasticsearch.action.admin.cluster.stats.MappingStats.lambda$of$0(MappingStats.java:91) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:38) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:39) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:39) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:39) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:39) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:39) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:39) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingVisitor.visitMapping(MappingVisitor.java:19) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.MappingStats.of(MappingStats.java:73) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction$MetadataStatsCache.lambda$refresh$0(TransportClusterStatsAction.java:293) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.ActionListener.completeWith(ActionListener.java:299) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction$MetadataStatsCache.refresh(TransportClusterStatsAction.java:293) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction$MetadataStatsCache.refresh(TransportClusterStatsAction.java:278) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.common.util.CancellableSingleObjectCache$CachedItem.startRefresh(CancellableSingleObjectCache.java:289) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.common.util.CancellableSingleObjectCache.get(CancellableSingleObjectCache.java:167) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction.newResponseAsync(TransportClusterStatsAction.java:132) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.admin.cluster.stats.TransportClusterStatsAction.newResponseAsync(TransportClusterStatsAction.java:58) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.support.nodes.TransportNodesAction$1.lambda$onCompletion$1(TransportNodesAction.java:142) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.support.nodes.TransportNodesAction.lambda$doExecute$0(TransportNodesAction.java:152) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.ActionListenerImplementations$ResponseWrappingActionListener.onResponse(ActionListenerImplementations.java:236) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.action.support.ThreadedActionListener$1.doRun(ThreadedActionListener.java:50) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:983) ~[elasticsearch-8.11.1.jar:?] at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:26) ~[elasticsearch-8.11.1.jar:?] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] at java.lang.Thread.run(Thread.java:1583) ~[?:?]
server/src/main/java/org/elasticsearch/action/admin/cluster/stats/MappingStats.java
out.writeOptionalVLong(totalMappingSizeBytes);
        } 
        out.writeCollection(fieldTypeStats);
        out.writeCollection(runtimeFieldStats);
    }
    private static OptionalLong ofNullable(Long l) {
        return l == null ? OptionalLong.empty() : OptionalLong.of(l);
    }
    /**
     * @return the total number of fields (in non-system indices), or {@link OptionalLong#empty()} if omitted (due to BwC)
     */
    public OptionalLong getTotalFieldCount() {
        return ofNullable(totalFieldCount);
    }
    /**
     * @return the total number of fields (in non-system indices) accounting for deduplication, or {@link OptionalLong#empty()} if omitted
     * (due to BwC)
     */
    public OptionalLong getTotalDeduplicatedFieldCount() {
        return ofNullable(totalDeduplicatedFieldCount);
    }
    /**
     * @return the total size of all mappings (including those for system indices) accounting for deduplication and compression, or {@link
     * OptionalLong#empty()} if omitted (due to BwC).
     */
    public OptionalLong getTotalMappingSizeBytes() {
        return ofNullable(totalMappingSizeBytes);
    }
    /**
     * Return stats about field types.