diff --git a/src/box/lua/call.cc b/src/box/lua/call.cc
index 786954c886505819339b44a13bc40e0f3ee0737a..5f1003e8caa9967922431c1e44c9d1d5489e4ff7 100644
--- a/src/box/lua/call.cc
+++ b/src/box/lua/call.cc
@@ -340,9 +340,9 @@ lbox_raise(lua_State *L)
 {
 	if (lua_gettop(L) == 0) {
 		/* re-throw saved exceptions (if any) */
-		if (cord()->exc == NULL)
+		if (cord()->exception == NULL)
 			return 0;
-		cord()->exc->raise();
+		cord()->exception->raise();
 		return 0;
 	}
 
diff --git a/src/exception.cc b/src/exception.cc
index d0486336903bb6cf0b421e525e288d9e2e1f9a36..64d739dc6842746b759b8b505d53d2f014bbfdd9 100644
--- a/src/exception.cc
+++ b/src/exception.cc
@@ -35,38 +35,42 @@
 #include <errno.h>
 
 /* Statically allocate out-of-memory exception */
-static ClientError out_of_memory(__FILE__, __LINE__, ER_MEMORY_ISSUE, 0,
+ClientError out_of_memory(__FILE__, __LINE__, ER_MEMORY_ISSUE, 0,
 			  "exception", "new");
 
-void*
+void *
 Exception::operator new(size_t size)
 {
-	/* Explicity call destructor for previous exception */
-	if (cord()->exc)
-		cord()->exc->~Exception();
-
-	/* Reuse memory allocated for exception */
-	if (cord()->exc_size < size) {
-		size_t new_size = cord()->exc_size > 0 ? cord()->exc_size : 512;
-		while (new_size < size)
-			new_size *= 2;
-		void *exc = realloc(cord()->exc, new_size);
-		if (exc == NULL)
-			throw &out_of_memory;
-		cord()->exc = (Exception *) exc;
-		cord()->exc_size = new_size;
-	}
+	struct cord *cord = cord();
 
-	return cord()->exc;
+	if (cord->exception == &out_of_memory) {
+		assert(cord->exception_size == 0);
+		cord->exception = NULL;
+	}
+	if (cord->exception) {
+		/* Explicitly call destructor for previous exception */
+		cord->exception->~Exception();
+		if (cord->exception_size >= size) {
+			/* Reuse memory allocated for exception */
+			return cord->exception;
+		}
+		free(cord->exception);
+	}
+	cord->exception = (ClientError *) malloc(size);
+	if (cord->exception) {
+		cord->exception_size = size;
+		return cord->exception;
+	}
+	cord->exception = &out_of_memory;
+	cord->exception_size = 0;
+	throw cord->exception;
 }
 
 void
-Exception::operator delete(void*)
+Exception::operator delete(void * /* ptr */)
 {
-	/* Free memory allocated for exception */
-	free(cord()->exc);
-	cord()->exc = NULL;
-	cord()->exc_size = 0;
+	/* Unsupported */
+	assert(false);
 }
 
 Exception::Exception(const char *file, unsigned line)
diff --git a/src/exception.h b/src/exception.h
index dcf01dc2262599ed0d81803bd9d604006a7997eb..a98317ed68eb53c3daf88b895dbceb3a80df8e86 100644
--- a/src/exception.h
+++ b/src/exception.h
@@ -33,12 +33,14 @@
 #include "errcode.h"
 #include "say.h"
 
+
 class Exception: public Object {
 public:
 	void *operator new(size_t size);
 	void operator delete(void*);
 	virtual void raise()
 	{
+		/* Throw the most specific type of exception */
 		throw this;
 	}
 
@@ -119,6 +121,8 @@ class ClientError: public Exception {
 	int m_errcode;
 };
 
+extern ClientError out_of_memory;
+
 class LoggedError: public ClientError {
 public:
 	template <typename ... Args>
diff --git a/src/fiber.cc b/src/fiber.cc
index 63fd8ccdb3e4424b11c9855b9e8977a201498e51..7042c3477b0b0e06e930c7266c7c3d9ed2e53754 100644
--- a/src/fiber.cc
+++ b/src/fiber.cc
@@ -527,8 +527,10 @@ cord_destroy(struct cord *cord)
 	slab_cache_destroy(&cord->slabc);
 	ev_loop_destroy(cord->loop);
 	/* Cleanup memory allocated for exceptions */
-	if (cord->exc)
-		delete cord->exc;
+	if (cord->exception && cord->exception != &out_of_memory) {
+		cord->exception->~Exception();
+		free(cord->exception);
+	}
 }
 
 struct cord_thread_arg
diff --git a/src/fiber.h b/src/fiber.h
index e1a10de3b101cbf2b6fa0a24e60b098a9a128330..60e5e602c34dca9313492070743b8eb7689779bf 100644
--- a/src/fiber.h
+++ b/src/fiber.h
@@ -153,8 +153,8 @@ struct cord {
 	struct slab_cache slabc;
 	char name[FIBER_NAME_MAX];
 	/** Last thrown exception */
-	struct Exception *exc;
-	size_t exc_size;
+	struct Exception *exception;
+	size_t exception_size;
 };
 
 extern __thread struct cord *cord_ptr;