diff --git a/src/network/access/qabstractprotocolhandler_p.h b/src/network/access/qabstractprotocolhandler_p.h
index da5eaeeb74c4..42925a169d34 100644
--- a/src/network/access/qabstractprotocolhandler_p.h
+++ b/src/network/access/qabstractprotocolhandler_p.h
@@ -17,6 +17,8 @@
 
 #include <QtNetwork/private/qtnetworkglobal_p.h>
 
+#include <QtCore/qtpreprocessorsupport.h>
+
 QT_REQUIRE_CONFIG(http);
 
 QT_BEGIN_NAMESPACE
@@ -34,6 +36,13 @@ public:
     virtual void _q_receiveReply() = 0;
     virtual void _q_readyRead() = 0;
     virtual bool sendRequest() = 0;
+    // Called when the reply is being destroyed and removing itself from any other internals
+    virtual bool tryRemoveReply(QHttpNetworkReply *reply)
+    {
+        Q_UNUSED(reply);
+        // base implementation is a noop
+        return false;
+    }
     void setReply(QHttpNetworkReply *reply);
 
 protected:
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index 87dc504ee126..a99921f52881 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -151,15 +151,6 @@ void QHttp2ProtocolHandler::handleConnectionClosure()
     h2Connection->handleConnectionClosure();
 }
 
-void QHttp2ProtocolHandler::_q_replyDestroyed(QObject *reply)
-{
-    QPointer<QHttp2Stream> stream = streamIDs.take(reply);
-    requestReplyPairs.remove(stream);
-    QObject::disconnect(stream, nullptr, this, nullptr);
-    if (stream && stream->isActive())
-        stream->sendRST_STREAM(CANCEL);
-}
-
 void QHttp2ProtocolHandler::_q_uploadDataDestroyed(QObject *uploadData)
 {
     QPointer<QHttp2Stream> stream = streamIDs.take(uploadData);
@@ -262,6 +253,25 @@ bool QHttp2ProtocolHandler::sendRequest()
     return true;
 }
 
+/*!
+    \internal
+    This gets called during destruction of \a reply, so do not call any functions
+    on \a reply. We check if there is a stream associated with the reply and,
+    if there is, we remove the request-reply pair associated with this stream,
+    delete the stream and return \c{true}. Otherwise nothing happens and we
+    return \c{false}.
+*/
+bool QHttp2ProtocolHandler::tryRemoveReply(QHttpNetworkReply *reply)
+{
+    QHttp2Stream *stream = streamIDs.take(reply);
+    if (stream) {
+        requestReplyPairs.remove(stream);
+        stream->deleteLater();
+        return true;
+    }
+    return false;
+}
+
 bool QHttp2ProtocolHandler::sendHEADERS(QHttp2Stream *stream, QHttpNetworkRequest &request)
 {
     using namespace HPack;
@@ -623,8 +633,6 @@ void QHttp2ProtocolHandler::connectStream(const HttpMessagePair &message, QHttp2
     auto *replyPrivate = reply->d_func();
     replyPrivate->connection = m_connection;
     replyPrivate->connectionChannel = m_channel;
-    connect(reply, &QObject::destroyed, this, &QHttp2ProtocolHandler::_q_replyDestroyed,
-            Qt::UniqueConnection);
 
     reply->setHttp2WasUsed(true);
     QPointer<QHttp2Stream> &oldStream = streamIDs[reply];
diff --git a/src/network/access/qhttp2protocolhandler_p.h b/src/network/access/qhttp2protocolhandler_p.h
index ecbc6823dcfd..aca8a0b6f66b 100644
--- a/src/network/access/qhttp2protocolhandler_p.h
+++ b/src/network/access/qhttp2protocolhandler_p.h
@@ -61,7 +61,6 @@ public:
     Q_INVOKABLE void handleConnectionClosure();
 
 private slots:
-    void _q_replyDestroyed(QObject *reply);
     void _q_uploadDataDestroyed(QObject *uploadData);
 
 private:
@@ -70,6 +69,7 @@ private:
     void _q_readyRead() override;
     Q_INVOKABLE void _q_receiveReply() override;
     Q_INVOKABLE bool sendRequest() override;
+    bool tryRemoveReply(QHttpNetworkReply *reply) override;
 
     bool sendSETTINGS_ACK();
     bool sendHEADERS(QHttp2Stream *stream, QHttpNetworkRequest &request);
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index cf7aad1930de..4f105af084a8 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -1002,6 +1002,13 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
             QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
             return;
         }
+        // Check if the h2 protocol handler already started processing it
+        if ((connectionType == QHttpNetworkConnection::ConnectionTypeHTTP2Direct
+             || channels[i].switchedToHttp2)
+            && channels[i].protocolHandler) {
+            if (channels[i].protocolHandler->tryRemoveReply(reply))
+                return;
+        }
     }
     // remove from the high priority queue
     if (!highPriorityQueue.isEmpty()) {
