diff --git a/mirai-core/src/commonMain/kotlin/network/handler/selector/AbstractKeepAliveNetworkHandlerSelector.kt b/mirai-core/src/commonMain/kotlin/network/handler/selector/AbstractKeepAliveNetworkHandlerSelector.kt
index c89b77f66..0a326a857 100644
--- a/mirai-core/src/commonMain/kotlin/network/handler/selector/AbstractKeepAliveNetworkHandlerSelector.kt
+++ b/mirai-core/src/commonMain/kotlin/network/handler/selector/AbstractKeepAliveNetworkHandlerSelector.kt
@@ -158,6 +158,13 @@ internal abstract class AbstractKeepAliveNetworkHandlerSelector<H : NetworkHandl
                         // 不可挽救
                         exceptionCollector.throwLast()
                     }
+                } catch (e: TimeoutCancellationException) {
+                    logIfEnabled { "... failed with TimeoutCancellationException: $e" }
+                    exceptionCollector.collect(e)
+                    close(e) // close H
+                    logIfEnabled { "CLOSED instance" }
+                    // 发包超时 可挽救
+                    return false
                 } catch (e: Throwable) {
                     // 不可挽救
                     logIfEnabled { "... failed with unexpected: $e" }
diff --git a/mirai-core/src/commonTest/kotlin/network/impl/common/CommonNHBotNormalLoginTest.kt b/mirai-core/src/commonTest/kotlin/network/impl/common/CommonNHBotNormalLoginTest.kt
index 9dc53ae7b..84491359d 100644
--- a/mirai-core/src/commonTest/kotlin/network/impl/common/CommonNHBotNormalLoginTest.kt
+++ b/mirai-core/src/commonTest/kotlin/network/impl/common/CommonNHBotNormalLoginTest.kt
@@ -12,8 +12,7 @@
 package net.mamoe.mirai.internal.network.impl.common
 
 import io.ktor.utils.io.errors.*
-import kotlinx.coroutines.delay
-import kotlinx.coroutines.isActive
+import kotlinx.coroutines.*
 import net.mamoe.mirai.internal.BotAccount
 import net.mamoe.mirai.internal.MockConfiguration
 import net.mamoe.mirai.internal.QQAndroidBot
@@ -30,6 +29,7 @@ import net.mamoe.mirai.internal.network.handler.selector.KeepAliveNetworkHandler
 import net.mamoe.mirai.internal.network.handler.selector.NetworkChannelException
 import net.mamoe.mirai.internal.network.handler.selector.SelectorNetworkHandler
 import net.mamoe.mirai.internal.network.handler.selectorLogger
+import net.mamoe.mirai.internal.network.impl.HeartbeatFailedException
 import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
 import net.mamoe.mirai.internal.test.runBlockingUnit
 import net.mamoe.mirai.network.CustomLoginFailedException
@@ -91,6 +91,19 @@ internal class CommonNHBotNormalLoginTest : AbstractCommonNHTest() {
         assertState(NetworkHandler.State.CLOSED)
     }
 
+    // #1963
+    @Test
+    fun `test first login failure with internally handled exceptions3`() = runBlockingUnit {
+        setSsoProcessor {
+            //Throw TimeoutCancellationException
+            withTimeout(1) {
+                delay(1000)
+            }
+        }
+        assertFailsWith<TimeoutCancellationException>("test TimeoutCancellationException") { bot.login() }
+        assertState(NetworkHandler.State.CLOSED)
+    }
+
     // 经过 #1963 考虑后在初次登录遇到任何错误都终止并传递异常
 //    @Test
 //    fun `test network broken`() = runBlockingUnit {
@@ -113,9 +126,36 @@ internal class CommonNHBotNormalLoginTest : AbstractCommonNHTest() {
         bot.network.close(StatSvc.ReqMSFOffline.MsfOfflineToken(0, 0, 0))
 
         eventDispatcher.joinBroadcast()
-        delay(1000L) // auto resume in BotOfflineEventMonitor
+        yield() // auto resume in BotOfflineEventMonitor
         eventDispatcher.joinBroadcast()
 
         assertState(NetworkHandler.State.OK)
     }
+
+    // #2504, #2488
+    @Test
+    fun `test resume failed with TimeoutCancellationException`() = runBlockingUnit {
+        var first = true
+        var failCount = 3
+        setSsoProcessor {
+            if (first) {
+                first = false
+            } else {
+                if (failCount > 0) {
+                    failCount--
+                    //Throw TimeoutCancellationException
+                    withTimeout(1) {
+                        delay(1000)
+                    }
+                }
+            }
+        }
+        bot.login()
+        bot.network.close(HeartbeatFailedException("Heartbeat Timeout", RuntimeException("Timeout stub"), true))
+        eventDispatcher.joinBroadcast()
+        yield() // auto resume in BotOfflineEventMonitor
+        eventDispatcher.joinBroadcast()
+        assertState(NetworkHandler.State.OK)
+    }
+
 }