diff --git a/src/lua/console.lua b/src/lua/console.lua
index 11fd8000f8312790ce48404b377860df759593c1..dc0541f68cd5fd6f39768facd3241eb1003ed996 100644
--- a/src/lua/console.lua
+++ b/src/lua/console.lua
@@ -24,19 +24,28 @@ local function format(status, ...)
     local function wrapnull(v)
         return v == nil and formatter.NULL or v
     end
-    if not status then
-        local v = ...
-        return formatter.encode({{error = wrapnull(v) }})
-    end
-    local count = select('#', ...)
-    if count == 0 then
-        return "---\n...\n"
-    end
-    local res = {}
-    for i=1,count,1 do
-        table.insert(res, wrapnull(select(i, ...)))
+    local err
+    if status then
+        local count = select('#', ...)
+        if count == 0 then
+            return "---\n...\n"
+        end
+        local res = {}
+        for i=1,count,1 do
+            table.insert(res, wrapnull(select(i, ...)))
+        end
+        -- serializer can raise an exception
+        status, err = pcall(formatter.encode, res)
+        if status then
+            return err
+        else
+            err = 'console: an exception occurred during formatting result: '..
+                tostring(err)
+        end
+    else
+        err = wrapnull(...)
     end
-    return formatter.encode(res)
+    return formatter.encode({{error = err }})
 end
 
 --
diff --git a/test/app/console.result b/test/app/console.result
index 40596ba7e469aa898ae91efc7b5cbc639a151dfa..0f603e15142dd99903dacadc7a93d2633947f2ca 100644
--- a/test/app/console.result
+++ b/test/app/console.result
@@ -1,5 +1,5 @@
 TAP version 13
-1..26
+1..28
 ok - console.listen started
 ok - Handshake
 ok - connect to console
@@ -18,6 +18,8 @@ ok - remote eval
 ok - remote state.remote.host
 ok - remote state.remote.port
 ok - remote state.prompt
+ok - exception handling
+ok - exception handling
 ok - remote disconnect
 ok - console.listen stopped
 ok - console.listen uri support
diff --git a/test/app/console.test.lua b/test/app/console.test.lua
index 680edb14637870922a10bccd714db9e7ef81f4ed..483b3e4ecd4a0f196f92bedd76f167c8c37880f3 100755
--- a/test/app/console.test.lua
+++ b/test/app/console.test.lua
@@ -20,7 +20,7 @@ local EOL = "\n%.%.%.\n"
 
 test = tap.test("console")
 
-test:plan(26)
+test:plan(28)
 
 -- Start console and connect to it
 local server = console.listen(CONSOLE_SOCKET)
@@ -98,6 +98,14 @@ test:is(state.remote.port, IPROTO_SOCKET, "remote state.remote.port")
 test:is(state.prompt, string.format("%s:%s", "unix/", IPROTO_SOCKET),
         "remote state.prompt")
 
+-- Check exception handling (gh-643)
+client:write("error('test')\n")
+test:ok(yaml.decode(client:read(EOL))[1].error:match('test') ~= nil,
+    "exception handling")
+client:write("setmetatable({}, { __serialize = function() error('test') end})\n")
+test:ok(yaml.decode(client:read(EOL))[1].error:match('test') ~= nil,
+    "exception handling")
+
 -- Disconnect from iproto
 client:write("~.\n")
 -- Check that iproto console has been disconnected