diff --git a/py/objstr.c b/py/objstr.c
index f91e1731c5b28ef926c984b6959e7be5bb4f4f81..814dd9e132fc811376f4745503bced29aca0e91a 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -894,9 +894,17 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
             } else {
                 if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
                     terse_str_format_value_error();
-                } else {
+                } else if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_NORMAL) {
                     nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
-                        "end of format while looking for conversion specifier"));
+                        "bad conversion specifier"));
+                } else {
+                    if (str >= top) {
+                        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                            "end of format while looking for conversion specifier"));
+                    } else {
+                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+                            "unknown conversion specifier %c", *str));
+                    }
                 }
             }
         }
@@ -989,15 +997,9 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kwa
             mp_print_kind_t print_kind;
             if (conversion == 's') {
                 print_kind = PRINT_STR;
-            } else if (conversion == 'r') {
-                print_kind = PRINT_REPR;
             } else {
-                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
-                    terse_str_format_value_error();
-                } else {
-                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
-                        "unknown conversion specifier %c", conversion));
-                }
+                assert(conversion == 'r');
+                print_kind = PRINT_REPR;
             }
             vstr_t arg_vstr;
             mp_print_t arg_print;
diff --git a/tests/basics/string_format.py b/tests/basics/string_format.py
index 55d843e1e16cbbd141a0d5e00d6a46a062dd7c23..b0e49f530a93238a0679e163d4ee2f4783eb6719 100644
--- a/tests/basics/string_format.py
+++ b/tests/basics/string_format.py
@@ -140,6 +140,13 @@ try:
 except ValueError:
     print('ValueError')
 
+# end of format parsing conversion specifier
+try:
+    '{!'.format('a')
+except ValueError:
+    print('ValueError')
+
+# unknown conversion specifier
 try:
     'abc{!d}'.format('1')
 except ValueError:
@@ -150,6 +157,7 @@ try:
 except ValueError:
     print('ValueError')
 
+# expected ':' after specifier
 try:
     '{!s :}'.format(2)
 except ValueError: