diff --git a/src/box/errcode.h b/src/box/errcode.h
index e9990340fd32c4e8e5c485581eae60d80d866c8a..0c1310bdf5e99fed630a27bc18d439e384484186 100644
--- a/src/box/errcode.h
+++ b/src/box/errcode.h
@@ -254,6 +254,7 @@ struct errcode_record {
 	/*199 */_(ER_FUNC_INDEX_FORMAT,		"Key format doesn't match one defined in functional index '%s' of space '%s': %s") \
 	/*200 */_(ER_FUNC_INDEX_PARTS,		"Wrong functional index definition: %s") \
 	/*201 */_(ER_NO_SUCH_FIELD_NAME,	"Field '%s' was not found in the tuple") \
+	/*202 */_(ER_FUNC_WRONG_ARG_COUNT,	"Wrong number of arguments is passed to %s(): expected %s, got %d") \
 
 /*
  * !IMPORTANT! Please follow instructions at start of the file
diff --git a/src/box/sql/expr.c b/src/box/sql/expr.c
index 1f9d9170569b8d94ee3b5069b71d03a90d89383a..1957bd4c8e48a55f8e9c985ecd950f1eacc009f8 100644
--- a/src/box/sql/expr.c
+++ b/src/box/sql/expr.c
@@ -4049,7 +4049,8 @@ sqlExprCodeTarget(Parse * pParse, Expr * pExpr, int target)
 			 * is done using ANSI rules from
 			 * collations_check_compatibility().
 			 */
-			if ((pDef->funcFlags & SQL_FUNC_NEEDCOLL) != 0) {
+			if ((pDef->funcFlags & SQL_FUNC_NEEDCOLL) != 0 &&
+			    nFarg > 0) {
 				struct coll *unused = NULL;
 				uint32_t curr_id = COLL_NONE;
 				bool is_curr_forced = false;
diff --git a/src/box/sql/func.c b/src/box/sql/func.c
index 07c019db9577e2fde10d010be274408b9dd02853..0c28cec297ca4e3d5952a3c3a4b3508dd21f8342 100644
--- a/src/box/sql/func.c
+++ b/src/box/sql/func.c
@@ -81,8 +81,13 @@ minmaxFunc(sql_context * context, int argc, sql_value ** argv)
 	int iBest;
 	struct coll *pColl;
 
-	assert(argc > 1);
 	mask = sql_user_data(context) == 0 ? 0 : -1;
+	if (argc < 2) {
+		diag_set(ClientError, ER_FUNC_WRONG_ARG_COUNT,
+		mask ? "GREATEST" : "LEAST", "at least two", argc);
+		context->is_aborted = true;
+		return;
+	}
 	pColl = sqlGetFuncCollSeq(context);
 	assert(mask == -1 || mask == 0);
 	iBest = 0;
diff --git a/test/box/misc.result b/test/box/misc.result
index 204c2671bfe17568bea26bfc8ec9c5656c9793f9..c46c5a9d6aff05ec264b5dacea0734efd6b7e34d 100644
--- a/test/box/misc.result
+++ b/test/box/misc.result
@@ -531,6 +531,7 @@ t;
   199: box.error.FUNC_INDEX_FORMAT
   200: box.error.FUNC_INDEX_PARTS
   201: box.error.NO_SUCH_FIELD_NAME
+  202: box.error.FUNC_WRONG_ARG_COUNT
 ...
 test_run:cmd("setopt delimiter ''");
 ---
diff --git a/test/sql-tap/func5.test.lua b/test/sql-tap/func5.test.lua
index 0b255e6593017cfee97db781cecbf0337a7d9940..e84ca25be7dafecc8429f739ff7df7b48d514c14 100755
--- a/test/sql-tap/func5.test.lua
+++ b/test/sql-tap/func5.test.lua
@@ -1,6 +1,6 @@
 #!/usr/bin/env tarantool
 test = require("sqltester")
-test:plan(19)
+test:plan(22)
 
 --!./tcltestrunner.lua
 -- 2010 August 27
@@ -257,4 +257,25 @@ test:do_execsql_test(
         SELECT LEAST(false, 'STR', 1, 0.5);
     ]], { false } )
 
+-- gh-4453: GREATEST()/LEAST() require at least two arguments
+-- be passed to these functions.
+--
+test:do_catchsql_test(
+    "func-5-5.1",
+    [[
+        SELECT LEAST(false);
+    ]], { 1, "Wrong number of arguments is passed to LEAST(): expected at least two, got 1" } )
+
+test:do_catchsql_test(
+    "func-5-5.2",
+    [[
+        SELECT GREATEST('abc');
+    ]], { 1, "Wrong number of arguments is passed to GREATEST(): expected at least two, got 1" } )
+
+test:do_catchsql_test(
+    "func-5-5.3",
+    [[
+        SELECT LEAST();
+    ]], { 1, "Wrong number of arguments is passed to LEAST(): expected at least two, got 0" } )
+
 test:finish_test()