diff --git a/src/test/java/org/jetbrains/plugins/ideavim/action/change/insert/InsertNormalExitModeActionTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/action/change/insert/InsertNormalExitModeActionTest.kt
new file mode 100644
index 000000000..65bba9ac3
--- /dev/null
+++ b/src/test/java/org/jetbrains/plugins/ideavim/action/change/insert/InsertNormalExitModeActionTest.kt
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2003-2024 The IdeaVim authors
+ *
+ * Use of this source code is governed by an MIT-style
+ * license that can be found in the LICENSE.txt file or at
+ * https://opensource.org/licenses/MIT.
+ */
+
+package org.jetbrains.plugins.ideavim.action.change.insert
+
+import com.maddyhome.idea.vim.state.mode.Mode
+import org.jetbrains.plugins.ideavim.VimTestCase
+import org.junit.jupiter.api.Test
+
+class InsertNormalExitModeActionTest : VimTestCase() {
+  @Test
+  fun `test exit insert normal mode`() {
+    doTest("i<C-O><Esc>", "12${c}3", "12${c}3", Mode.INSERT)
+  }
+}
diff --git a/src/test/java/org/jetbrains/plugins/ideavim/command/VimShowModeTest.kt b/src/test/java/org/jetbrains/plugins/ideavim/command/VimShowModeTest.kt
index 106ba728d..929e013ea 100644
--- a/src/test/java/org/jetbrains/plugins/ideavim/command/VimShowModeTest.kt
+++ b/src/test/java/org/jetbrains/plugins/ideavim/command/VimShowModeTest.kt
@@ -98,6 +98,14 @@ class VimShowModeTest : VimTestCase() {
     assertEquals("(insert)", statusString)
   }
 
+  @Test
+  fun `test status string after escape out of Insert Normal mode`() {
+    configureByText("123")
+    typeText("i<C-O><Esc>")
+    val statusString = VimModeWidget.getModeText(fixture.editor.vim.mode)
+    assertEquals("INSERT", statusString)
+  }
+
   @Test
   fun `test status string for Replace pending Normal mode`() {
     configureByText("123")
diff --git a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/key/consumers/EditorResetConsumer.kt b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/key/consumers/EditorResetConsumer.kt
index d87b81a1c..05fdd82c1 100644
--- a/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/key/consumers/EditorResetConsumer.kt
+++ b/vim-engine/src/main/kotlin/com/maddyhome/idea/vim/key/consumers/EditorResetConsumer.kt
@@ -60,19 +60,26 @@ class EditorResetConsumer : KeyConsumer {
     if (commandBuilder.isEmpty) {
       val register = injector.registerGroup
       if (register.currentRegister == register.defaultRegister) {
-        var indicateError = true
-        if (key.keyCode == KeyEvent.VK_ESCAPE) {
-          val executed = arrayOf<Boolean?>(null)
-          injector.actionExecutor.executeCommand(
-            editor,
-            { executed[0] = injector.actionExecutor.executeEsc(editor, context) },
-            "",
-            null,
-          )
-          indicateError = !executed[0]!!
+        // Escape should exit "Insert Normal" mode. We don't have a handler for <Esc> in Normal mode, so we do it here
+        val mode = editor.mode
+        if (mode is Mode.NORMAL && (mode.isInsertPending || mode.isReplacePending)) {
+          editor.mode = mode.returnTo
         }
-        if (indicateError) {
-          injector.messages.indicateError()
+        else {
+          var indicateError = true
+          if (key.keyCode == KeyEvent.VK_ESCAPE) {
+            val executed = arrayOf<Boolean?>(null)
+            injector.actionExecutor.executeCommand(
+              editor,
+              { executed[0] = injector.actionExecutor.executeEsc(editor, context) },
+              "",
+              null,
+            )
+            indicateError = !executed[0]!!
+          }
+          if (indicateError) {
+            injector.messages.indicateError()
+          }
         }
       }
     }