diff --git a/Makefile.am b/Makefile.am
index 180e80e73c4f767dc167b4a927142683c700721b..8ca0267645b30bb443e63e7a00c5dbca7b10e5ba 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -102,6 +102,7 @@ test_cases = \
 	tests/extensions/include/rfc.svtest \
 	tests/extensions/include/execute.svtest \
 	tests/extensions/imap4flags/basic.svtest \
+	tests/extensions/imap4flags/errors.svtest \
 	tests/extensions/imap4flags/hasflag.svtest \
 	tests/extensions/imap4flags/execute.svtest \
 	tests/extensions/imap4flags/multiscript.svtest \
diff --git a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c
index 691c27b1a0013dc519601d1c56e476d0e8356cfe..9ee2c5f6e819ac711e7fa981e9c6eb93101965a6 100644
--- a/src/lib-sieve/plugins/imap4flags/tst-hasflag.c
+++ b/src/lib-sieve/plugins/imap4flags/tst-hasflag.c
@@ -99,8 +99,6 @@ static bool
 tst_hasflag_validate(struct sieve_validator *valdtr,
 		     struct sieve_command *tst)
 {
-	struct sieve_ast_argument *vars = tst->first_positional;
-	struct sieve_ast_argument *keys = sieve_ast_argument_next(vars);
 	const struct sieve_match_type mcht_default =
 		SIEVE_MATCH_TYPE_DEFAULT(is_match_type);
 	const struct sieve_comparator cmp_default =
@@ -109,6 +107,9 @@ tst_hasflag_validate(struct sieve_validator *valdtr,
 	if (!ext_imap4flags_command_validate(valdtr, tst))
 		return FALSE;
 
+	struct sieve_ast_argument *vars = tst->first_positional;
+	struct sieve_ast_argument *keys = sieve_ast_argument_next(vars);
+
 	if (keys == NULL) {
 		keys = vars;
 		vars = NULL;
diff --git a/tests/extensions/imap4flags/errors.svtest b/tests/extensions/imap4flags/errors.svtest
new file mode 100644
index 0000000000000000000000000000000000000000..2f873ab04e037aada73fd8e9d09a22ede10a512e
--- /dev/null
+++ b/tests/extensions/imap4flags/errors.svtest
@@ -0,0 +1,18 @@
+require "vnd.dovecot.testsuite";
+
+require "relational";
+require "comparator-i;ascii-numeric";
+
+/*
+ * Invalid syntax
+ */
+
+test "Invalid Syntax" {
+        if test_script_compile "errors/syntax.sieve" {
+                test_fail "compile should have failed";
+        }
+
+        if not test_error :count "eq" :comparator "i;ascii-numeric" "31" {
+                test_fail "wrong number of errors reported";
+        }
+}
diff --git a/tests/extensions/imap4flags/errors/syntax.sieve b/tests/extensions/imap4flags/errors/syntax.sieve
new file mode 100644
index 0000000000000000000000000000000000000000..b619943c5a7b05717535f02246a9bce612b5eec8
--- /dev/null
+++ b/tests/extensions/imap4flags/errors/syntax.sieve
@@ -0,0 +1,46 @@
+require "imap4flags";
+
+# 1-10: Used incorrectly as a command vs test
+if setflag {}
+if addflag {}
+if removeflag {}
+if setflag;
+if addflag;
+if removeflag;
+hasflag;
+
+# 11-19: Used with no argument
+setflag;
+addflag;
+removeflag;
+if hasflag {}
+if hasflag;
+if not hasflag {}
+if not hasflag;
+
+# Used with one string argument (OK)
+setflag "frop";
+addflag "frop";
+removeflag "frop";
+if hasflag "frop" {}
+
+# 20-25: Used with one number argument
+setflag 234234;
+addflag 23423;
+removeflag 234234;
+if hasflag 234234 {}
+if hasflag 234234;
+
+# Used with one string list argument (OK)
+setflag ["frop"];
+addflag ["frop"];
+removeflag ["frop"];
+if hasflag ["frop"] {}
+
+# 26-30: Used with unknown tag
+setflag :frop "frop";
+addflag :frop "frop";
+removeflag :frop "frop";
+if hasflag :frop "frop" {}
+if hasflag :frop "frop";
+