diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h
index ab234b447d66ae970a868fe337c83832db8b6502..59f246e2b829ee64e3bf4454da111a5518368d85 100644
--- a/bare-arm/mpconfigport.h
+++ b/bare-arm/mpconfigport.h
@@ -12,6 +12,8 @@
 #define MICROPY_HELPER_REPL         (0)
 #define MICROPY_HELPER_LEXER_UNIX   (0)
 #define MICROPY_ENABLE_SOURCE_LINE  (0)
+#define MICROPY_ENABLE_DOC_STRING   (0)
+#define MICROPY_ERROR_REPORTING     (MICROPY_ERROR_REPORTING_TERSE)
 #define MICROPY_PY_BUILTINS_BYTEARRAY (0)
 #define MICROPY_PY_BUILTINS_MEMORYVIEW (0)
 #define MICROPY_PY_BUILTINS_FROZENSET (0)
@@ -31,8 +33,6 @@
 #define MICROPY_LONGINT_IMPL        (MICROPY_LONGINT_IMPL_NONE)
 #define MICROPY_FLOAT_IMPL          (MICROPY_FLOAT_IMPL_NONE)
 
-//#define MICROPY_ERROR_REPORTING     (MICROPY_ERROR_REPORTING_TERSE)
-
 // type definitions for the specific machine
 
 #define BYTES_PER_WORD (4)
diff --git a/py/argcheck.c b/py/argcheck.c
index c8daa6033750254353ad0a62e0648bf461f65337..f151eb02fdd2d924887ef3bc4ae659f758b5de31 100644
--- a/py/argcheck.c
+++ b/py/argcheck.c
@@ -34,28 +34,49 @@
 #include "obj.h"
 #include "runtime.h"
 
+STATIC NORETURN void terse_arg_mismatch(void) {
+    nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "argument num/types mismatch"));
+}
+
 void mp_arg_check_num(mp_uint_t n_args, mp_uint_t n_kw, mp_uint_t n_args_min, mp_uint_t n_args_max, bool takes_kw) {
     // TODO maybe take the function name as an argument so we can print nicer error messages
 
     if (n_kw && !takes_kw) {
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments"));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            terse_arg_mismatch();
+        } else {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "function does not take keyword arguments"));
+        }
     }
 
     if (n_args_min == n_args_max) {
         if (n_args != n_args_min) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
-                                                    "function takes %d positional arguments but %d were given",
-                                                    n_args_min, n_args));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                terse_arg_mismatch();
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                    "function takes %d positional arguments but %d were given",
+                    n_args_min, n_args));
+            }
         }
     } else {
         if (n_args < n_args_min) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
-                                                    "function missing %d required positional arguments",
-                                                    n_args_min - n_args));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                terse_arg_mismatch();
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                    "function missing %d required positional arguments",
+                    n_args_min - n_args));
+            }
         } else if (n_args > n_args_max) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
-                                                    "function expected at most %d arguments, got %d",
-                                                    n_args_max, n_args));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                terse_arg_mismatch();
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                    "function expected at most %d arguments, got %d",
+                    n_args_max, n_args));
+            }
         }
     }
 }
@@ -74,7 +95,13 @@ void mp_arg_parse_all(mp_uint_t n_pos, const mp_obj_t *pos, mp_map_t *kws, mp_ui
             mp_map_elem_t *kw = mp_map_lookup(kws, MP_OBJ_NEW_QSTR(allowed[i].qstr), MP_MAP_LOOKUP);
             if (kw == NULL) {
                 if (allowed[i].flags & MP_ARG_REQUIRED) {
-                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' argument required", qstr_str(allowed[i].qstr)));
+                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                        terse_arg_mismatch();
+                    } else {
+                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                            "'%s' argument required",
+                            qstr_str(allowed[i].qstr)));
+                    }
                 }
                 out_vals[i] = allowed[i].defval;
                 continue;
@@ -94,13 +121,23 @@ void mp_arg_parse_all(mp_uint_t n_pos, const mp_obj_t *pos, mp_map_t *kws, mp_ui
         }
     }
     if (pos_found < n_pos) {
-        // TODO better error message
         extra_positional:
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "extra positional arguments given"));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            terse_arg_mismatch();
+        } else {
+            // TODO better error message
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "extra positional arguments given"));
+        }
     }
     if (kws_found < kws->used) {
-        // TODO better error message
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "extra keyword arguments given"));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            terse_arg_mismatch();
+        } else {
+            // TODO better error message
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "extra keyword arguments given"));
+        }
     }
 }
 
diff --git a/py/builtin.c b/py/builtin.c
index 77b58575ae26c154432a5a390dcf61eff9b8f511..b337af3c59658f9ce2f8b6a9917e23c851f1ff2a 100644
--- a/py/builtin.c
+++ b/py/builtin.c
@@ -272,7 +272,14 @@ STATIC mp_obj_t mp_builtin_divmod(mp_obj_t o1_in, mp_obj_t o2_in) {
         return mp_obj_new_tuple(2, tuple);
     #endif
     } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported operand type(s) for divmod(): '%s' and '%s'", mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "unsupported operand type(s) for divmod()"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "unsupported operand type(s) for divmod(): '%s' and '%s'",
+                mp_obj_get_type_str(o1_in), mp_obj_get_type_str(o2_in)));
+        }
     }
 }
 MP_DEFINE_CONST_FUN_OBJ_2(mp_builtin_divmod_obj, mp_builtin_divmod);
@@ -357,8 +364,8 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
     mp_uint_t len;
     const char *str = mp_obj_str_get_data(o_in, &len);
     #if MICROPY_PY_BUILTINS_STR_UNICODE
-    mp_uint_t charlen = unichar_charlen(str, len);
-    if (charlen == 1) {
+    len = unichar_charlen(str, len);
+    if (len == 1) {
         if (MP_OBJ_IS_STR(o_in) && UTF8_IS_NONASCII(*str)) {
             mp_int_t ord = *str++ & 0x7F;
             for (mp_int_t mask = 0x40; ord & mask; mask >>= 1) {
@@ -371,17 +378,21 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
         } else {
             return mp_obj_new_int(((const byte*)str)[0]);
         }
-    } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", charlen));
     }
     #else
     if (len == 1) {
         // don't sign extend when converting to ord
         return mp_obj_new_int(((const byte*)str)[0]);
-    } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "ord() expected a character, but string of length %d found", len));
     }
     #endif
+
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+            "ord expects a character"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+            "ord() expected a character, but string of length %d found", len));
+    }
 }
 MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_ord_obj, mp_builtin_ord);
 
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 7ecf0919b27b490ed1ae8d6e53447092a95ed1ab..c96a7d4ae229b2741517f3476cb790dba97b3165 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -118,7 +118,12 @@ STATIC void do_load(mp_obj_t module_obj, vstr_t *file) {
 
     if (lex == NULL) {
         // we verified the file exists using stat, but lexer could still fail
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "No module named '%s'", vstr_str(file)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
+                "no module named '%s'", vstr_str(file)));
+        }
     }
 
     #if MICROPY_PY___FILE__
@@ -277,7 +282,12 @@ mp_obj_t mp_builtin___import__(mp_uint_t n_args, const mp_obj_t *args) {
                 {
                 #endif
                     // couldn't find the file, so fail
-                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "No module named '%s'", qstr_str(mod_name)));
+                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                        nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found"));
+                    } else {
+                        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError,
+                            "no module named '%s'", qstr_str(mod_name)));
+                    }
                 }
             } else {
                 // found the file, so get the module
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 02c6674d8bc6866907a0236a4a8a392a8eb29cbe..0c214bb5b663f09a6271340e9e19fba00f723ca6 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -238,7 +238,7 @@ typedef long long mp_longint_impl_t;
 #define MICROPY_ENABLE_DOC_STRING (0)
 #endif
 
-// Exception messages are short static strings (TODO)
+// Exception messages are short static strings
 #define MICROPY_ERROR_REPORTING_TERSE    (1)
 // Exception messages provide basic error details
 #define MICROPY_ERROR_REPORTING_NORMAL   (2)
diff --git a/py/obj.c b/py/obj.c
index 02f75c7c40d23d1f224618a10ff6962feeac7532..e9fed19c6c944d26b2b60693ce906f161ad6eb76 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -177,7 +177,12 @@ mp_int_t mp_obj_hash(mp_obj_t o_in) {
     // TODO delegate to __hash__ method if it exists
 
     } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unhashable type: '%s'", mp_obj_get_type_str(o_in)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "unhashable type"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "unhashable type: '%s'", mp_obj_get_type_str(o_in)));
+        }
     }
 }
 
@@ -230,9 +235,14 @@ bool mp_obj_equal(mp_obj_t o1, mp_obj_t o2) {
         }
     }
 
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError,
-        "Equality for '%s' and '%s' types not yet implemented", mp_obj_get_type_str(o1), mp_obj_get_type_str(o2)));
-    return false;
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_NotImplementedError,
+            "equality for given types not yet implemented"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NotImplementedError,
+            "equality for '%s' and '%s' types not yet implemented",
+            mp_obj_get_type_str(o1), mp_obj_get_type_str(o2)));
+    }
 }
 
 mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
@@ -248,7 +258,13 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
     } else if (MP_OBJ_IS_TYPE(arg, &mp_type_int)) {
         return mp_obj_int_get_checked(arg);
     } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "can't convert to int"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "can't convert %s to int", mp_obj_get_type_str(arg)));
+        }
     }
 }
 
@@ -283,7 +299,13 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
     } else if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
         return mp_obj_float_get(arg);
     } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "can't convert to float"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "can't convert %s to float", mp_obj_get_type_str(arg)));
+        }
     }
 }
 
@@ -307,7 +329,13 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
     } else if (MP_OBJ_IS_TYPE(arg, &mp_type_complex)) {
         mp_obj_complex_get(arg, real, imag);
     } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "can't convert to complex"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "can't convert %s to complex", mp_obj_get_type_str(arg)));
+        }
     }
 }
 #endif
@@ -319,7 +347,13 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
     } else if (MP_OBJ_IS_TYPE(o, &mp_type_list)) {
         mp_obj_list_get(o, len, items);
     } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "expected tuple/list"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
+        }
     }
 }
 
@@ -327,7 +361,13 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) {
     mp_uint_t seq_len;
     mp_obj_get_array(o, &seq_len, items);
     if (seq_len != len) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "requested length %d but object has length %d", len, seq_len));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                "tuple/list has wrong length"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+                "requested length %d but object has length %d", len, seq_len));
+        }
     }
 }
 
@@ -337,7 +377,14 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index,
     if (MP_OBJ_IS_SMALL_INT(index)) {
         i = MP_OBJ_SMALL_INT_VALUE(index);
     } else if (!mp_obj_get_int_maybe(index, &i)) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%s indices must be integers, not %s", qstr_str(type->name), mp_obj_get_type_str(index)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "indices must be integers"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "%s indices must be integers, not %s",
+                qstr_str(type->name), mp_obj_get_type_str(index)));
+        }
     }
 
     if (i < 0) {
@@ -351,7 +398,12 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index,
         }
     } else {
         if (i < 0 || i >= len) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "%s index out of range", qstr_str(type->name)));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "index out of range"));
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError,
+                    "%s index out of range", qstr_str(type->name)));
+            }
         }
     }
     return i;
@@ -379,7 +431,13 @@ mp_obj_t mp_obj_id(mp_obj_t o_in) {
 mp_obj_t mp_obj_len(mp_obj_t o_in) {
     mp_obj_t len = mp_obj_len_maybe(o_in);
     if (len == MP_OBJ_NULL) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "object has no len"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
+        }
     } else {
         return len;
     }
@@ -414,11 +472,29 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
         // TODO: call base classes here?
     }
     if (value == MP_OBJ_NULL) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item deletion", mp_obj_get_type_str(base)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "object does not support item deletion"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "'%s' object does not support item deletion", mp_obj_get_type_str(base)));
+        }
     } else if (value == MP_OBJ_SENTINEL) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not subscriptable", mp_obj_get_type_str(base)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "object is not subscriptable"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "'%s' object is not subscriptable", mp_obj_get_type_str(base)));
+        }
     } else {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "object does not support item assignment"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "'%s' object does not support item assignment", mp_obj_get_type_str(base)));
+        }
     }
 }
 
diff --git a/py/objstr.c b/py/objstr.c
index 5146f36f5035488a58baea12f14b589a24e9fd2f..97a5a7d0f78b8c70d770c966f859bc38c744ba2e 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -143,12 +143,13 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
     }
 #endif
 
+    mp_arg_check_num(n_args, n_kw, 0, 3, false);
+
     switch (n_args) {
         case 0:
             return MP_OBJ_NEW_QSTR(MP_QSTR_);
 
-        case 1:
-        {
+        case 1: {
             vstr_t *vstr = vstr_new();
             mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[0], PRINT_STR);
             mp_obj_t s = mp_obj_new_str(vstr->buf, vstr->len, false);
@@ -156,9 +157,7 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
             return s;
         }
 
-        case 2:
-        case 3:
-        {
+        default: // 2 or 3 args
             // TODO: validate 2nd/3rd args
             if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) {
                 GET_STR_DATA_LEN(args[0], str_data, str_len);
@@ -172,10 +171,6 @@ STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw,
                 mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ);
                 return mp_obj_new_str(bufinfo.buf, bufinfo.len, false);
             }
-        }
-
-        default:
-            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments"));
     }
 }
 
@@ -251,7 +246,7 @@ STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_k
     return mp_obj_str_builder_end(o);
 
 wrong_args:
-        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments"));
+    nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments"));
 }
 
 // like strstr but with specified length and allows \0 bytes
@@ -831,6 +826,10 @@ static mp_obj_t arg_as_int(mp_obj_t arg) {
     return arg;
 }
 
+STATIC NORETURN void terse_str_format_value_error(void) {
+    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad format string"));
+}
+
 mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
     assert(MP_OBJ_IS_STR_OR_BYTES(args[0]));
 
@@ -848,7 +847,12 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
                 vstr_add_char(vstr, '}');
                 continue;
             }
-            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "single '}' encountered in format string"));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                terse_str_format_value_error();
+            } else {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                    "single '}' encountered in format string"));
+            }
         }
         if (*str != '{') {
             vstr_add_char(vstr, *str);
@@ -882,7 +886,12 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
             if (str < top && (*str == 'r' || *str == 's')) {
                 conversion = *str++;
             } else {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "end of format while looking for conversion specifier"));
+                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                    terse_str_format_value_error();
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                        "end of format while looking for conversion specifier"));
+                }
             }
         }
 
@@ -902,17 +911,32 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
             }
         }
         if (str >= top) {
-            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "unmatched '{' in format"));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                terse_str_format_value_error();
+            } else {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                    "unmatched '{' in format"));
+            }
         }
         if (*str != '}') {
-            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "expected ':' after format specifier"));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                terse_str_format_value_error();
+            } else {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                    "expected ':' after format specifier"));
+            }
         }
 
         mp_obj_t arg = mp_const_none;
 
         if (field_name) {
             if (arg_i > 0) {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "can't switch from automatic field numbering to manual field specification"));
+                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                    terse_str_format_value_error();
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                        "can't switch from automatic field numbering to manual field specification"));
+                }
             }
             int index = 0;
             if (str_to_int(vstr_str(field_name), &index) != vstr_len(field_name) - 1) {
@@ -927,7 +951,12 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
             field_name = NULL;
         } else {
             if (arg_i < 0) {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "can't switch from manual field specification to automatic field numbering"));
+                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                    terse_str_format_value_error();
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                        "can't switch from manual field specification to automatic field numbering"));
+                }
             }
             if (arg_i >= n_args - 1) {
                 nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "tuple index out of range"));
@@ -945,7 +974,12 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
             } else if (conversion == 'r') {
                 print_kind = PRINT_REPR;
             } else {
-                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "unknown conversion specifier %c", conversion));
+                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));
+                }
             }
             vstr_t *arg_vstr = vstr_new();
             mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, arg_vstr, arg, print_kind);
@@ -1030,10 +1064,20 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
 
         if (sign) {
             if (type == 's') {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sign not allowed in string format specifier"));
+                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                    terse_str_format_value_error();
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                        "sign not allowed in string format specifier"));
+                }
             }
             if (type == 'c') {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Sign not allowed with integer format specifier 'c'"));
+                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                    terse_str_format_value_error();
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                        "sign not allowed with integer format specifier 'c'"));
+                }
             }
         } else {
             sign = '-';
@@ -1089,8 +1133,13 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
                     break;
 
                 default:
-                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
-                        "unknown format code '%c' for object of type '%s'", type, mp_obj_get_type_str(arg)));
+                    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 format code '%c' for object of type '%s'",
+                            type, mp_obj_get_type_str(arg)));
+                    }
             }
         }
 
@@ -1151,15 +1200,24 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
 #endif
 
                 default:
-                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
-                        "unknown format code '%c' for object of type 'float'",
-                        type, mp_obj_get_type_str(arg)));
+                    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 format code '%c' for object of type 'float'",
+                            type, mp_obj_get_type_str(arg)));
+                    }
             }
         } else {
             // arg doesn't look like a number
 
             if (align == '=') {
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "'=' alignment not allowed in string format specifier"));
+                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                    terse_str_format_value_error();
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                        "'=' alignment not allowed in string format specifier"));
+                }
             }
 
             switch (type) {
@@ -1181,9 +1239,13 @@ mp_obj_t mp_obj_str_format(mp_uint_t n_args, const mp_obj_t *args) {
                 }
 
                 default:
-                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
-                        "unknown format code '%c' for object of type 'str'",
-                        type, mp_obj_get_type_str(arg)));
+                    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 format code '%c' for object of type 'str'",
+                            type, mp_obj_get_type_str(arg)));
+                    }
             }
         }
     }
@@ -1223,7 +1285,12 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
             const byte *key = ++str;
             while (*str != ')') {
                 if (str >= top) {
-                    nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "incomplete format key"));
+                    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                        terse_str_format_value_error();
+                    } else {
+                        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                            "incomplete format key"));
+                    }
                 }
                 ++str;
             }
@@ -1280,7 +1347,12 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, mp_uint_t n_args, const mp_o
         }
 
         if (str >= top) {
-            nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "incomplete format"));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                terse_str_format_value_error();
+            } else {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+                    "incomplete format"));
+            }
         }
 
         // Tuple value lookup
@@ -1297,25 +1369,17 @@ not_enough_args:
                     mp_uint_t len;
                     const char *s = mp_obj_str_get_data(arg, &len);
                     if (len != 1) {
-                        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "%%c requires int or char"));
-                        break;
+                        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                            "%%c requires int or char"));
                     }
                     pfenv_print_strn(&pfenv_vstr, s, 1, flags, ' ', width);
-                    break;
-                }
-                if (arg_looks_integer(arg)) {
+                } else if (arg_looks_integer(arg)) {
                     char ch = mp_obj_get_int(arg);
                     pfenv_print_strn(&pfenv_vstr, &ch, 1, flags, ' ', width);
-                    break;
-                }
-#if MICROPY_PY_BUILTINS_FLOAT
-                // This is what CPython reports, so we report the same.
-                if (MP_OBJ_IS_TYPE(arg, &mp_type_float)) {
-                    nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "integer argument expected, got float"));
-
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                        "integer required"));
                 }
-#endif
-                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "an integer is required"));
                 break;
 
             case 'd':
@@ -1366,9 +1430,13 @@ not_enough_args:
                 break;
 
             default:
-                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
-                    "unsupported format character '%c' (0x%x) at index %d",
-                    *str, *str, str - start_str));
+                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,
+                        "unsupported format character '%c' (0x%x) at index %d",
+                        *str, *str, str - start_str));
+                }
         }
     }
 
@@ -1871,7 +1939,14 @@ bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2) {
 }
 
 STATIC void bad_implicit_conversion(mp_obj_t self_in) {
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(self_in)));
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+            "can't convert to str implicitly"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+            "can't convert '%s' object to str implicitly",
+            mp_obj_get_type_str(self_in)));
+    }
 }
 
 STATIC void arg_type_mixup() {
diff --git a/py/objtype.c b/py/objtype.c
index 70dc226a60387b0579b9096ef09ef0f29c5825cf..55a321d98c91ba61cbdccc89b73032e29b0bbc10 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -313,7 +313,13 @@ mp_obj_t instance_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, c
             m_del(mp_obj_t, args2, 2 + n_args + 2 * n_kw);
         }
         if (init_ret != mp_const_none) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                    "__init__() should return None"));
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                    "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
+            }
         }
 
     }
@@ -617,7 +623,13 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw
     };
     mp_obj_class_lookup(&lookup, self->base.type);
     if (member[0] == MP_OBJ_NULL) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(self_in)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "object not callable"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "'%s' object is not callable", mp_obj_get_type_str(self_in)));
+        }
     }
     if (member[0] == MP_OBJ_SENTINEL) {
         return mp_call_function_n_kw(self->subobj[0], n_args, n_kw, args);
@@ -691,7 +703,12 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, co
     mp_obj_type_t *self = self_in;
 
     if (self->make_new == NULL) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%s' instances", qstr_str(self->name)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "cannot create instance"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "cannot create '%s' instances", qstr_str(self->name)));
+        }
     }
 
     // make new instance
@@ -787,7 +804,13 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
         mp_obj_type_t *t = items[i];
         // TODO: Verify with CPy, tested on function type
         if (t->make_new == NULL) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "type '%s' is not an acceptable base type", qstr_str(t->name)));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                    "type is not an acceptable base type"));
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                    "type '%s' is not an acceptable base type", qstr_str(t->name)));
+            }
         }
     }
 
@@ -996,9 +1019,7 @@ mp_obj_t mp_instance_cast_to_native_base(mp_const_obj_t self_in, mp_const_obj_t
 STATIC mp_obj_t static_class_method_make_new(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
     assert(self_in == &mp_type_staticmethod || self_in == &mp_type_classmethod);
 
-    if (n_args != 1 || n_kw != 0) {
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "function takes 1 positional argument but %d were given", n_args));
-    }
+    mp_arg_check_num(n_args, n_kw, 1, 1, false);
 
     mp_obj_static_class_method_t *o = m_new_obj(mp_obj_static_class_method_t);
     *o = (mp_obj_static_class_method_t){{(mp_obj_type_t*)self_in}, args[0]};
diff --git a/py/parsenum.c b/py/parsenum.c
index f7f43ac9b504f055b3eff10881318d6a8c9ef606..bb88eb729bb249a5b0ff638c9880369ca0d4256b 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -138,7 +138,13 @@ overflow:
     }
 
 value_error:
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid syntax for integer with base %d: '%s'", base, str));
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+            "invalid syntax for integer"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+            "invalid syntax for integer with base %d: '%s'", base, str));
+    }
 }
 
 typedef enum {
diff --git a/py/runtime.c b/py/runtime.c
index e225ba8b05861064e27d32d5f291fb072427db43..c0ae4726f2af682da21f3b3b262d5de4637d2ac9 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -165,7 +165,13 @@ mp_obj_t mp_load_global(qstr qstr) {
         // TODO lookup in dynamic table of builtins first
         elem = mp_map_lookup((mp_map_t*)&mp_builtin_object_dict_obj.map, MP_OBJ_NEW_QSTR(qstr), MP_MAP_LOOKUP);
         if (elem == NULL) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%s' is not defined", qstr_str(qstr)));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError,
+                    "name not defined"));
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError,
+                    "name '%s' is not defined", qstr_str(qstr)));
+            }
         }
     }
     return elem->value;
@@ -231,8 +237,15 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
                 return result;
             }
         }
-        // TODO specify in error message what the operator is
-        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "bad operand type for unary operator: '%s'", mp_obj_get_type_str(arg)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "unsupported type for operator"));
+        } else {
+            // TODO specify in error message what the operator is
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "bad operand type for unary operator: '%s'",
+                mp_obj_get_type_str(arg)));
+        }
     }
 }
 
@@ -496,10 +509,13 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
             return mp_const_false;
         }
 
-        nlr_raise(mp_obj_new_exception_msg_varg(
-                     &mp_type_TypeError, "'%s' object is not iterable",
-                     mp_obj_get_type_str(rhs)));
-        return mp_const_none;
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                "object not iterable"));
+        } else {
+            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                "'%s' object is not iterable", mp_obj_get_type_str(rhs)));
+        }
     }
 
     // generic binary_op supplied by type
@@ -515,12 +531,16 @@ generic_binary_op:
 
     // TODO implement dispatch for reverse binary ops
 
-    // TODO specify in error message what the operator is
 unsupported_op:
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
-        "unsupported operand types for binary operator: '%s', '%s'",
-        mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
-    return mp_const_none;
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+            "unsupported type for operator"));
+    } else {
+        // TODO specify in error message what the operator is
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+            "unsupported operand types for binary operator: '%s', '%s'",
+            mp_obj_get_type_str(lhs), mp_obj_get_type_str(rhs)));
+    }
 
 zero_division:
     nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero"));
@@ -556,7 +576,13 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args, mp_uint_t n_kw
         return type->call(fun_in, n_args, n_kw, args);
     }
 
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+            "object not callable"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+            "'%s' object is not callable", mp_obj_get_type_str(fun_in)));
+    }
 }
 
 // args contains: fun  self/NULL  arg(0)  ...  arg(n_args-2)  arg(n_args-1)  kw_key(0)  kw_val(0)  ... kw_key(n_kw-1)  kw_val(n_kw-1)
@@ -746,9 +772,21 @@ void mp_unpack_sequence(mp_obj_t seq_in, mp_uint_t num, mp_obj_t *items) {
     return;
 
 too_short:
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", seq_len));
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+            "wrong number of values to unpack"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+            "need more than %d values to unpack", seq_len));
+    }
 too_long:
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", num));
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+            "wrong number of values to unpack"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+            "too many values to unpack (expected %d)", num));
+    }
 }
 
 // unpacked items are stored in reverse order into the array pointed to by items
@@ -809,7 +847,13 @@ void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) {
     return;
 
 too_short:
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", seq_len));
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError,
+            "wrong number of values to unpack"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
+            "need more than %d values to unpack", seq_len));
+    }
 }
 
 mp_obj_t mp_load_attr(mp_obj_t base, qstr attr) {
@@ -891,12 +935,20 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) {
 
     if (dest[0] == MP_OBJ_NULL) {
         // no attribute/method called attr
-        // following CPython, we give a more detailed error message for type objects
-        if (MP_OBJ_IS_TYPE(base, &mp_type_type)) {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
-                "type object '%s' has no attribute '%s'", qstr_str(((mp_obj_type_t*)base)->name), qstr_str(attr)));
+        if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+            nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError,
+                "no such attribute"));
         } else {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
+            // following CPython, we give a more detailed error message for type objects
+            if (MP_OBJ_IS_TYPE(base, &mp_type_type)) {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
+                    "type object '%s' has no attribute '%s'",
+                    qstr_str(((mp_obj_type_t*)base)->name), qstr_str(attr)));
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
+                    "'%s' object has no attribute '%s'",
+                    mp_obj_get_type_str(base), qstr_str(attr)));
+            }
         }
     }
 }
@@ -909,7 +961,14 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) {
             return;
         }
     }
-    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%s'", mp_obj_get_type_str(base), qstr_str(attr)));
+    if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+        nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError,
+            "no such attribute"));
+    } else {
+        nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError,
+            "'%s' object has no attribute '%s'",
+            mp_obj_get_type_str(base), qstr_str(attr)));
+    }
 }
 
 mp_obj_t mp_getiter(mp_obj_t o_in) {
@@ -936,7 +995,13 @@ mp_obj_t mp_getiter(mp_obj_t o_in) {
             } else {
                 // object not iterable
 not_iterable:
-                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
+                if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                    nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                        "object not iterable"));
+                } else {
+                    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                        "'%s' object is not iterable", mp_obj_get_type_str(o_in)));
+                }
             }
         }
     }
@@ -956,7 +1021,13 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {
             // __next__ exists, call it and return its result
             return mp_call_method_n_kw(0, 0, dest);
         } else {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                    "object not an iterator"));
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                    "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+            }
         }
     }
 }
@@ -986,7 +1057,13 @@ mp_obj_t mp_iternext(mp_obj_t o_in) {
                 }
             }
         } else {
-            nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+            if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+                nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError,
+                    "object not an iterator"));
+            } else {
+                nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+                    "'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
+            }
         }
     }
 }