We saw a case where the recovery stats reported `recovered_bytes` greater than `length_in_bytes` for one file:

```
GET /_recovery?detailed

200 OK
...
{
  "name": "_buk.fdt",
  "length_in_bytes": 26891307173,
  "reused": false,
  "recovered_in_bytes": 35324928266,
  "recovered_from_snapshot_in_bytes": 8433621093
}
...
```

NB `35324928266 == 26891307173 + 8433621093`

This causes Elasticsearch to compute a negative value for the reserved space on the target node of this recovery, which prevents stats APIs from working. This appears to be caused by a network-level failure which triggers a retry without first cancelling an ongoing download of a different file with the same name from the snapshot repository.

---

### Workaround

Restart the target node to clear these stats.
server/src/main/java/org/elasticsearch/index/shard/IndexShard.java
if (state == IndexShardState.STARTED) {
            
            return getEngine().acquireIndexCommitForSnapshot();
        } else {
            throw new IllegalIndexShardStateException(shardId, state, "snapshot is not allowed");
        }
    }
    /**
     * Snapshots the most recent safe index commit from the currently running engine.
     * All index files referenced by this index commit won't be freed until the commit/snapshot is closed.
     */
    public Engine.IndexCommitRef acquireSafeIndexCommit() throws EngineException {
        final IndexShardState state = this.state; 
        
        if (state == IndexShardState.STARTED || state == IndexShardState.CLOSED) {
            return getEngine().acquireSafeIndexCommit();
        } else {
            throw new IllegalIndexShardStateException(shardId, state, "snapshot is not allowed");
        }
    }
    /**
     * gets a {@link Store.MetadataSnapshot} for the current directory. This method is safe to call in all lifecycle of the index shard,
     * without having to worry about the current state of the engine and concurrent flushes.
     *
     * @throws org.apache.lucene.index.IndexNotFoundException     if no index is found in the current directory
     * @throws org.apache.lucene.index.CorruptIndexException      if the lucene index is corrupted. This can be caused by a checksum
     *                                                            mismatch or an unexpected exception when opening the index reading the
     *                                                            segments file.
     * @throws org.apache.lucene.index.IndexFormatTooOldException if the lucene index is too old to be opened.
     * @throws org.apache.lucene.index.IndexFormatTooNewException if the lucene index is too new to be opened.