diff --git a/src/box/sql/vdbemem.c b/src/box/sql/vdbemem.c
index ac0dfa33340716f2b46536b91c4a698b463b8115..acffa97ba23adc9ae8a6f827cd05cfb5b7b238d3 100644
--- a/src/box/sql/vdbemem.c
+++ b/src/box/sql/vdbemem.c
@@ -263,6 +263,13 @@ sqlVdbeMemNulTerminate(Mem * pMem)
 	}
 }
 
+static inline bool
+mem_has_msgpack_subtype(struct Mem *mem)
+{
+	return (mem->flags & MEM_Subtype) != 0 &&
+	       mem->subtype == SQL_SUBTYPE_MSGPACK;
+}
+
 /*
  * Add MEM_Str to the set of representations for the given Mem.  Numbers
  * are converted using sql_snprintf().  Converting a BLOB to a string
@@ -281,15 +288,29 @@ int
 sqlVdbeMemStringify(Mem * pMem)
 {
 	int fg = pMem->flags;
-	const int nByte = 32;
+	int nByte = 32;
 
-	if ((fg & (MEM_Null | MEM_Str | MEM_Blob)) != 0)
+	if ((fg & (MEM_Null | MEM_Str | MEM_Blob)) != 0 &&
+	    !mem_has_msgpack_subtype(pMem))
 		return 0;
 
 	assert(!(fg & MEM_Zero));
-	assert((fg & (MEM_Int | MEM_UInt | MEM_Real | MEM_Bool)) != 0);
+	assert((fg & (MEM_Int | MEM_UInt | MEM_Real | MEM_Bool |
+		      MEM_Blob)) != 0);
 	assert(EIGHT_BYTE_ALIGNMENT(pMem));
 
+	/*
+	 * In case we have ARRAY/MAP we should save decoded value
+	 * before clearing pMem->z.
+	 */
+	char *value = NULL;
+	if (mem_has_msgpack_subtype(pMem)) {
+		const char *value_str = mp_str(pMem->z);
+		nByte = strlen(value_str) + 1;
+		value = region_alloc(&fiber()->gc, nByte);
+		memcpy(value, value_str, nByte);
+	}
+
 	if (sqlVdbeMemClearAndResize(pMem, nByte)) {
 		return -1;
 	}
@@ -302,6 +323,10 @@ sqlVdbeMemStringify(Mem * pMem)
 	} else if ((fg & MEM_Bool) != 0) {
 		sql_snprintf(nByte, pMem->z, "%s", pMem->u.b ? "true" : "false");
 		pMem->flags &= ~MEM_Bool;
+	} else if (mem_has_msgpack_subtype(pMem)) {
+		sql_snprintf(nByte, pMem->z, "%s", value);
+		pMem->flags &= ~MEM_Subtype;
+		pMem->subtype = SQL_SUBTYPE_NO;
 	} else {
 		assert(fg & MEM_Real);
 		sql_snprintf(nByte, pMem->z, "%!.15g", pMem->u.r);
@@ -1140,7 +1165,8 @@ valueToText(sql_value * pVal)
 {
 	assert(pVal != 0);
 	assert((pVal->flags & (MEM_Null)) == 0);
-	if (pVal->flags & (MEM_Blob | MEM_Str)) {
+	if ((pVal->flags & (MEM_Blob | MEM_Str)) &&
+	    !mem_has_msgpack_subtype(pVal)) {
 		if (ExpandBlob(pVal))
 			return 0;
 		pVal->flags |= MEM_Str;
@@ -1809,8 +1835,7 @@ mpstream_encode_vdbe_mem(struct mpstream *stream, struct Mem *var)
 		 * Emit BIN header iff the BLOB doesn't store
 		 * MsgPack content.
 		 */
-		if ((var->flags & MEM_Subtype) == 0 ||
-		     var->subtype != SQL_SUBTYPE_MSGPACK) {
+		if (!mem_has_msgpack_subtype(var)) {
 			uint32_t binl = var->n +
 					((var->flags & MEM_Zero) ?
 					var->u.nZero : 0);
diff --git a/test/sql/types.result b/test/sql/types.result
index 124a5ca976b47cab2174006db57daf182e4e03dd..03caea8bb77a367697739c3bafc83e2f4475d3d7 100644
--- a/test/sql/types.result
+++ b/test/sql/types.result
@@ -1589,3 +1589,105 @@ s:select()
 s:drop()
 ---
 ...
+--
+-- Make sure that the array/map conversion to scalar error is
+-- displayed correctly.
+--
+box.execute('CREATE TABLE t1(i INT PRIMARY KEY AUTOINCREMENT, a SCALAR);')
+---
+- row_count: 1
+...
+format = {}
+---
+...
+format[1] = {type = 'integer', name = 'I'}
+---
+...
+format[2] = {type = 'array', name = 'A'}
+---
+...
+s = box.schema.space.create('T2', {format=format})
+---
+...
+i = s:create_index('ii')
+---
+...
+s:insert({1, {1,2,3}})
+---
+- [1, [1, 2, 3]]
+...
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+---
+- null
+- 'Type mismatch: can not convert [1, 2, 3] to scalar'
+...
+s:replace({1, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}})
+---
+- [1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+    22, 23, 24, 25, 26, 27, 28, 29, 30]]
+...
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+---
+- null
+- 'Type mismatch: can not convert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30] to scalar'
+...
+--
+-- Make sure that the error will be displayed correctly even if
+-- the value is too long.
+--
+long_array = {}
+---
+...
+for i = 1,120 do long_array[i] = i end
+---
+...
+s:replace({1, long_array})
+---
+- [1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
+    22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
+    42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+    62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
+    82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
+    102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+    118, 119, 120]]
+...
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+---
+- null
+- 'Type mismatch: can not convert [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+  15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
+  35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+  55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
+  75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94,
+  95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+  112, 113, 114, 115, 116, 117, 11'
+...
+s:drop()
+---
+...
+format[2].type = 'map'
+---
+...
+s = box.schema.space.create('T2', {format=format})
+---
+...
+i = s:create_index('ii')
+---
+...
+s:insert({1, {b = 1}})
+---
+- [1, {'b': 1}]
+...
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+---
+- null
+- 'Type mismatch: can not convert {"b": 1} to scalar'
+...
+s:drop()
+---
+...
+box.execute('DROP TABLE t1;')
+---
+- row_count: 1
+...
diff --git a/test/sql/types.test.lua b/test/sql/types.test.lua
index ce933596c2eaf1e40019da2ccef1f00ddfffaced..f6fb64cabff132070039bed01cbb5a6dc8c35492 100644
--- a/test/sql/types.test.lua
+++ b/test/sql/types.test.lua
@@ -368,3 +368,34 @@ s:insert({1, true, {1, 2}, {a = 3}, 'asd'})
 box.execute('UPDATE t SET b = false WHERE i = 1;')
 s:select()
 s:drop()
+
+--
+-- Make sure that the array/map conversion to scalar error is
+-- displayed correctly.
+--
+box.execute('CREATE TABLE t1(i INT PRIMARY KEY AUTOINCREMENT, a SCALAR);')
+format = {}
+format[1] = {type = 'integer', name = 'I'}
+format[2] = {type = 'array', name = 'A'}
+s = box.schema.space.create('T2', {format=format})
+i = s:create_index('ii')
+s:insert({1, {1,2,3}})
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+s:replace({1, {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}})
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+--
+-- Make sure that the error will be displayed correctly even if
+-- the value is too long.
+--
+long_array = {}
+for i = 1,120 do long_array[i] = i end
+s:replace({1, long_array})
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+s:drop()
+format[2].type = 'map'
+s = box.schema.space.create('T2', {format=format})
+i = s:create_index('ii')
+s:insert({1, {b = 1}})
+box.execute('INSERT INTO t1(a) SELECT a FROM t2;')
+s:drop()
+box.execute('DROP TABLE t1;')