diff --git a/src/lib-sieve/sieve-binary-file.c b/src/lib-sieve/sieve-binary-file.c
index 54e65c0a115bbbfda78b266a47964a60a59d80fe..aa1fabf33f2dec1b8d8037fe0e946d7b42581579 100644
--- a/src/lib-sieve/sieve-binary-file.c
+++ b/src/lib-sieve/sieve-binary-file.c
@@ -68,12 +68,9 @@ sieve_binary_file_read_header(struct sieve_binary *sbin, int fd,
 			      enum sieve_error *error_code_r)
 {
 	struct sieve_binary_header header;
-	enum sieve_error error_code;
 	ssize_t rret;
 
-	if (error_code_r == NULL)
-		error_code_r = &error_code;
-	*error_code_r = SIEVE_ERROR_NONE;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	rret = pread(fd, &header, sizeof(header), 0);
 	if (rret == 0) {
@@ -158,15 +155,13 @@ sieve_binary_file_write_header(struct sieve_binary *sbin, int fd,
 	if (wret < 0) {
 		e_error(sbin->event, "update: "
 			"failed to write to binary: %m");
-		if (error_code_r != NULL)
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		return -1;
 	} else if (wret != sizeof(*header)) {
 		e_error(sbin->event, "update: "
 			"header written partially %zd/%zu",
 			wret, sizeof(*header));
-		if (error_code_r != NULL)
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		return -1;
 	}
 	return 0;
@@ -417,8 +412,7 @@ sieve_binary_do_save(struct sieve_binary *sbin, const char *path, bool update,
 	struct sieve_binary_extension_reg *const *regs;
 	unsigned int ext_count, i;
 
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	/* Check whether saving is necessary */
 	if (!update && sbin->path != NULL && strcmp(sbin->path, path) == 0) {
@@ -438,14 +432,12 @@ sieve_binary_do_save(struct sieve_binary *sbin, const char *path, bool update,
 				"failed to create temporary file: %s",
 				eacces_error_get_creating("open",
 							  str_c(temp_path)));
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_NO_PERMISSION;
+			*error_code_r = SIEVE_ERROR_NO_PERMISSION;
 		} else {
 			e_error(sbin->event, "save: "
 				"failed to create temporary file: "
 				"open(%s) failed: %m", str_c(temp_path));
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		}
 		return -1;
 	}
@@ -457,8 +449,10 @@ sieve_binary_do_save(struct sieve_binary *sbin, const char *path, bool update,
 
 		if (binext != NULL && binext->binary_pre_save != NULL &&
 		    !binext->binary_pre_save(regs[i]->extension, sbin,
-					     regs[i]->context, error_code_r))
+					     regs[i]->context, error_code_r)) {
+			i_assert(*error_code_r != SIEVE_ERROR_NONE);
 			return -1;
+		}
 	}
 
 	/* Save binary */
@@ -466,8 +460,7 @@ sieve_binary_do_save(struct sieve_binary *sbin, const char *path, bool update,
 	stream = o_stream_create_fd(fd, 0);
 	if (!sieve_binary_save_to_stream(sbin, stream)) {
 		result = -1;
-		if (error_code_r != NULL)
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		o_stream_ignore_last_errors(stream);
 	}
 	o_stream_destroy(&stream);
@@ -485,15 +478,13 @@ sieve_binary_do_save(struct sieve_binary *sbin, const char *path, bool update,
 			e_error(sbin->event, "save: "
 				"failed to save binary: %s",
 				eacces_error_get_creating("rename", path));
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_NO_PERMISSION;
+			*error_code_r = SIEVE_ERROR_NO_PERMISSION;
 		} else {
 			e_error(sbin->event, "save: "
 				"failed to save binary: "
 				"rename(%s, %s) failed: %m",
 				str_c(temp_path), path);
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		}
 		result = -1;
 	}
@@ -521,6 +512,7 @@ sieve_binary_do_save(struct sieve_binary *sbin, const char *path, bool update,
 			    !binext->binary_post_save(regs[i]->extension, sbin,
 						      regs[i]->context,
 						      error_code_r)) {
+				i_assert(*error_code_r != SIEVE_ERROR_NONE);
 				result = -1;
 				break;
 			}
@@ -558,28 +550,22 @@ sieve_binary_fd_open(struct sieve_binary *sbin, const char *path,
 {
 	int fd;
 
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-
 	fd = open(path, open_flags);
 	if (fd < 0) {
 		switch (errno) {
 		case ENOENT:
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_NOT_FOUND;
+			*error_code_r = SIEVE_ERROR_NOT_FOUND;
 			break;
 		case EACCES:
 			e_error(sbin->event, "open: "
 				"failed to open: %s",
 				eacces_error_get("open", path));
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_NO_PERMISSION;
+			*error_code_r = SIEVE_ERROR_NO_PERMISSION;
 			break;
 		default:
 			e_error(sbin->event, "open: "
 				"failed to open: open(%s) failed: %m", path);
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 			break;
 		}
 		return -1;
@@ -595,23 +581,27 @@ sieve_binary_file_open(struct sieve_binary *sbin, const char *path,
 	int fd, ret = 0;
 	struct stat st;
 
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	fd = sieve_binary_fd_open(sbin, path, O_RDONLY, error_code_r);
 	if (fd < 0)
 		return -1;
 
 	if (fstat(fd, &st) < 0) {
-		if (errno != ENOENT)
+		if (errno == ENOENT)
+			*error_code_r = SIEVE_ERROR_NOT_FOUND;
+		else {
 			e_error(sbin->event, "open: fstat(%s) failed: %m",
 				path);
+			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		}
 		ret = -1;
 	}
 
 	if (ret == 0 && !S_ISREG(st.st_mode)) {
 		e_error(sbin->event, "open: "
 			"binary is not a regular file");
+		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		ret = -1;
 	}
 
@@ -881,8 +871,7 @@ _sieve_binary_open(struct sieve_binary *sbin, enum sieve_error *error_code_r)
 	}
 
 	if (!result) {
-		if (error_code_r != NULL)
-			*error_code_r = SIEVE_ERROR_NOT_VALID;
+		*error_code_r = SIEVE_ERROR_NOT_VALID;
 		return FALSE;
 	}
 
@@ -903,8 +892,7 @@ _sieve_binary_open(struct sieve_binary *sbin, enum sieve_error *error_code_r)
 	} T_END;
 
 	if (!result) {
-		if (error_code_r != NULL)
-			*error_code_r = SIEVE_ERROR_NOT_VALID;
+		*error_code_r = SIEVE_ERROR_NOT_VALID;
 		return FALSE;
 	}
 	return TRUE;
@@ -921,6 +909,7 @@ int sieve_binary_open(struct sieve_instance *svinst, const char *path,
 
 	i_assert(script == NULL || sieve_script_svinst(script) == svinst);
 	*sbin_r = NULL;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	/* Create binary object */
 	sbin = sieve_binary_create(svinst, script);
@@ -953,8 +942,7 @@ int sieve_binary_open(struct sieve_instance *svinst, const char *path,
 		    !binext->binary_open(regs[i]->extension, sbin,
 					 regs[i]->context)) {
 			/* Extension thinks its corrupt */
-			if (error_code_r != NULL)
-				*error_code_r = SIEVE_ERROR_NOT_VALID;
+			*error_code_r = SIEVE_ERROR_NOT_VALID;
 			sieve_binary_unref(&sbin);
 			return -1;
 		}
@@ -968,9 +956,8 @@ int sieve_binary_check_executable(struct sieve_binary *sbin,
 				  enum sieve_error *error_code_r,
 				  const char **client_error_r)
 {
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
 	*client_error_r = NULL;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	if (HAS_ALL_BITS(sbin->header.flags,
 			 SIEVE_BINARY_FLAG_RESOURCE_LIMIT)) {
@@ -978,8 +965,7 @@ int sieve_binary_check_executable(struct sieve_binary *sbin,
 			"Binary execution is blocked: "
 			"Cumulative resource usage limit exceeded "
 			"(resource limit flag is set)");
-		if (error_code_r != NULL)
-			*error_code_r = SIEVE_ERROR_RESOURCE_LIMIT;
+		*error_code_r = SIEVE_ERROR_RESOURCE_LIMIT;
 		*client_error_r = "cumulative resource usage limit exceeded";
 		return 0;
 	}
@@ -1025,12 +1011,9 @@ sieve_binary_file_do_update_resource_usage(
 int sieve_binary_file_update_resource_usage(struct sieve_binary *sbin,
 					    enum sieve_error *error_code_r)
 {
-	enum sieve_error error_code;
 	int fd, ret = 0;
 
-	if (error_code_r == NULL)
-		error_code_r = &error_code;
-	*error_code_r = SIEVE_ERROR_NONE;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	sieve_binary_file_close(&sbin->file);
 
@@ -1042,11 +1025,14 @@ int sieve_binary_file_update_resource_usage(struct sieve_binary *sbin,
 	}
 
 	fd = sieve_binary_fd_open(sbin, sbin->path, O_RDWR, error_code_r);
-	if (fd < 0)
+	if (fd < 0) {
+		i_assert(*error_code_r != SIEVE_ERROR_NONE);
 		return -1;
+	}
 
 	ret = sieve_binary_file_do_update_resource_usage(sbin, fd,
 							 error_code_r);
+	i_assert(ret == 0 || *error_code_r != SIEVE_ERROR_NONE);
 
 	if (close(fd) < 0) {
 		e_error(sbin->event, "update: "
diff --git a/src/lib-sieve/sieve-common.h b/src/lib-sieve/sieve-common.h
index 53ccffbd1e4bf9d3cfe2ceac73f136eb9e8af48e..cedd0b6a2e01d938a1c1210a2d6b5409cddf9f20 100644
--- a/src/lib-sieve/sieve-common.h
+++ b/src/lib-sieve/sieve-common.h
@@ -210,6 +210,9 @@ struct sieve_instance {
  * Errors
  */
 
+void sieve_error_args_init(enum sieve_error **error_code_r,
+			   const char ***error_r);
+
 void sieve_error_create_internal(enum sieve_error *error_code_r,
 				 const char **error_r);
 
diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c
index f60042f62e746a2e7bf9248765fb550854b7d365..b15c197accda730757d2ae5254981f35bb72c10b 100644
--- a/src/lib-sieve/sieve-script.c
+++ b/src/lib-sieve/sieve-script.c
@@ -118,14 +118,10 @@ int sieve_script_create(struct sieve_instance *svinst,
 			enum sieve_error *error_code_r)
 {
 	struct sieve_storage *storage;
-	enum sieve_error error_code;
 	int ret;
 
 	*script_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	if (sieve_storage_create(svinst, location, 0,
 				 &storage, error_code_r) < 0)
@@ -172,13 +168,11 @@ void sieve_script_unref(struct sieve_script **_script)
 int sieve_script_open(struct sieve_script *script,
 		      enum sieve_error *error_code_r)
 {
-	enum sieve_error error_code;
+	struct sieve_storage *storage = script->storage;
 	int ret;
 
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	if (script->open)
 		return 0;
@@ -238,10 +232,6 @@ int sieve_script_check(struct sieve_instance *svinst, const char *location,
 		       const char *name, enum sieve_error *error_code_r)
 {
 	struct sieve_script *script;
-	enum sieve_error error_code;
-
-	if (error_code_r == NULL)
-		error_code_r = &error_code;
 
 	if (sieve_script_create_open(svinst, location, name,
 				     &script, error_code_r) < 0)
@@ -314,13 +304,10 @@ int sieve_script_get_stream(struct sieve_script *script,
 			    enum sieve_error *error_code_r)
 {
 	struct sieve_storage *storage = script->storage;
-	enum sieve_error error_code;
 	int ret;
 
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	if (script->stream != NULL) {
 		*stream_r = script->stream;
@@ -520,14 +507,12 @@ int sieve_script_binary_load(struct sieve_script *script,
 			     struct sieve_binary **sbin_r,
 			     enum sieve_error *error_code_r)
 {
-	enum sieve_error error_code;
+	struct sieve_storage *storage = script->storage;
 	int ret;
 
 	*sbin_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	if (script->v.binary_load == NULL) {
 		*error_code_r = SIEVE_ERROR_NOT_POSSIBLE;
@@ -544,13 +529,11 @@ int sieve_script_binary_save(struct sieve_script *script,
 			     struct sieve_binary *sbin, bool update,
 			     enum sieve_error *error_code_r)
 {
+	struct sieve_storage *storage = script->storage;
 	struct sieve_script *bin_script = sieve_binary_script(sbin);
-	enum sieve_error error_code;
 
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	i_assert(bin_script == NULL || sieve_script_equals(bin_script, script));
 
@@ -633,6 +616,7 @@ int sieve_script_rename(struct sieve_script *script, const char *newname)
 	int ret;
 
 	i_assert(newname != NULL);
+	sieve_storage_clear_error(storage);
 
 	/* Check script name */
 	if (!sieve_script_name_is_valid(newname)) {
@@ -692,6 +676,7 @@ int sieve_script_delete(struct sieve_script *script, bool ignore_active)
 	int ret = 0;
 
 	i_assert(script->open); // FIXME: auto-open?
+	sieve_storage_clear_error(storage);
 
 	/* Is the requested script active? */
 	if (sieve_script_is_active(script) > 0) {
@@ -745,6 +730,8 @@ int sieve_script_is_active(struct sieve_script *script)
 {
 	struct sieve_storage *storage = script->storage;
 
+	sieve_storage_clear_error(storage);
+
 	/* Special handling if this is a default script */
 	if (storage->default_storage_for != NULL) {
 		int ret = sieve_storage_active_script_is_default(
@@ -767,6 +754,7 @@ int sieve_script_activate(struct sieve_script *script, time_t mtime)
 	int ret = 0;
 
 	i_assert(script->open); // FIXME: auto-open?
+	sieve_storage_clear_error(storage);
 
 	if (storage->default_storage_for == NULL) {
 		i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0);
@@ -882,14 +870,10 @@ int sieve_script_sequence_create(struct sieve_instance *svinst,
 {
 	struct sieve_storage *storage;
 	struct sieve_script_sequence *sseq;
-	enum sieve_error error_code;
 	int ret;
 
 	*sseq_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	if (sieve_storage_create(svinst, location, 0,
 				 &storage, error_code_r) < 0)
@@ -910,13 +894,10 @@ int sieve_script_sequence_next(struct sieve_script_sequence *sseq,
 			       enum sieve_error *error_code_r)
 {
 	struct sieve_storage *storage = sseq->storage;
-	enum sieve_error error_code;
 
 	*script_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	i_assert(storage->v.script_sequence_next != NULL);
 	return storage->v.script_sequence_next(sseq, script_r, error_code_r);
diff --git a/src/lib-sieve/sieve-storage.c b/src/lib-sieve/sieve-storage.c
index c8be0c32bcf089b411da8f98ecc4e725f207102e..b40a221eb8898f67884148347c745832cf1f423c 100644
--- a/src/lib-sieve/sieve-storage.c
+++ b/src/lib-sieve/sieve-storage.c
@@ -325,15 +325,8 @@ sieve_storage_init(struct sieve_instance *svinst,
 	const char *const *options;
 	const char *location;
 	struct event *storage_event, *event;
-	enum sieve_error error_code;
 	int ret;
 
-	*storage_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
-
 	i_assert(storage_class->v.init != NULL);
 
 	storage_event = sieve_storage_create_event(svinst, svinst->event);
@@ -392,7 +385,6 @@ int sieve_storage_create(struct sieve_instance *svinst, const char *location,
 			 enum sieve_error *error_code_r)
 {
 	const struct sieve_storage *storage_class;
-	enum sieve_error error_code;
 	const char *data;
 	int ret;
 
@@ -400,10 +392,7 @@ int sieve_storage_create(struct sieve_instance *svinst, const char *location,
 	i_assert((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0);
 
 	*storage_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	data = location;
 	if ((ret = sieve_storage_driver_parse(svinst, &data,
@@ -512,14 +501,10 @@ int sieve_storage_create_personal(struct sieve_instance *svinst,
 {
 	struct sieve_storage *storage = NULL;
 	const char *set_default, *set_default_name;
-	enum sieve_error error_code;
 	int ret;
 
 	*storage_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	/* Check whether Sieve is disabled for this user */
 	if (!svinst->set->enabled) {
@@ -718,27 +703,20 @@ sieve_storage_get_script_direct(struct sieve_storage *storage, const char *name,
 {
 	int ret;
 
-	*script_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	sieve_storage_clear_error(storage);
-
 	/* Validate script name */
 	if (name != NULL && !sieve_script_name_is_valid(name)) {
 		sieve_storage_set_error(storage,
 			SIEVE_ERROR_BAD_PARAMS,
 			"Invalid script name '%s'.",
 			str_sanitize(name, 80));
-		if (error_code_r != NULL)
-			*error_code_r = storage->error_code;
+		*error_code_r = storage->error_code;
 		return -1;
 	}
 
 	i_assert(storage->v.get_script != NULL);
 	ret = storage->v.get_script(storage, name, script_r);
 	i_assert(ret <= 0);
-	if (error_code_r != NULL)
-		*error_code_r = storage->error_code;
+	*error_code_r = storage->error_code;
 	return ret;
 }
 
@@ -749,6 +727,8 @@ int sieve_storage_get_script(struct sieve_storage *storage, const char *name,
 	struct sieve_instance *svinst = storage->svinst;
 
 	*script_r = NULL;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	if (sieve_storage_get_script_direct(storage, name,
 					    script_r, error_code_r) == 0)
@@ -792,6 +772,8 @@ int sieve_storage_open_script(struct sieve_storage *storage, const char *name,
 	struct sieve_script *script;
 
 	*script_r = NULL;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	if (sieve_storage_get_script(storage, name, &script, error_code_r) < 0)
 		return -1;
@@ -838,11 +820,10 @@ sieve_storage_check_script_direct(struct sieve_storage *storage,
 				  enum sieve_error *error_code_r)
 {
 	struct sieve_script *script;
-	enum sieve_error error_code;
 	int ret;
 
-	if (error_code_r == NULL)
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	if (sieve_storage_get_script_direct(storage, name,
 					    &script, error_code_r) < 0)
@@ -858,10 +839,9 @@ int sieve_storage_check_script(struct sieve_storage *storage, const char *name,
 			       enum sieve_error *error_code_r)
 {
 	struct sieve_script *script;
-	enum sieve_error error_code;
 
-	if (error_code_r == NULL)
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
+	sieve_storage_clear_error(storage);
 
 	if (sieve_storage_open_script(storage, name, &script, error_code_r) < 0)
 		return (*error_code_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
@@ -931,14 +911,10 @@ int sieve_storage_active_script_open(struct sieve_storage *storage,
 {
 	struct sieve_instance *svinst = storage->svinst;
 	struct sieve_script *script = NULL;
-	enum sieve_error error_code;
 	int ret;
 
 	*script_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 	sieve_storage_clear_error(storage);
 
 	i_assert(storage->v.active_script_open != NULL);
@@ -948,7 +924,7 @@ int sieve_storage_active_script_open(struct sieve_storage *storage,
 	if (ret == 0 ||
 	    (storage->flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 ||
 	    storage->default_location == NULL) {
-		if (ret < 0 && error_code_r != NULL)
+		if (ret < 0)
 			*error_code_r = storage->error_code;
 		*script_r = script;
 		return ret;
@@ -973,6 +949,8 @@ int sieve_storage_deactivate(struct sieve_storage *storage, time_t mtime)
 
 	i_assert((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0);
 
+	sieve_storage_clear_error(storage);
+
 	i_assert(storage->v.deactivate != NULL);
 	ret = storage->v.deactivate(storage);
 
@@ -1014,6 +992,7 @@ int sieve_storage_list_init(struct sieve_storage *storage,
 	struct sieve_storage_list_context *lctx;
 
 	*lctx_r = NULL;
+	sieve_storage_clear_error(storage);
 
 	i_assert(storage->v.list_init != NULL);
 	if (storage->v.list_init(storage, &lctx) < 0)
@@ -1037,6 +1016,8 @@ sieve_storage_list_next(struct sieve_storage_list_context *lctx, bool *active_r)
 			(storage->flags &
 			 SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0);
 
+	sieve_storage_clear_error(storage);
+
 	i_assert(storage->v.list_next != NULL);
 	scriptname = storage->v.list_next(lctx, &script_active);
 
@@ -1137,6 +1118,8 @@ sieve_storage_save_init(struct sieve_storage *storage, const char *scriptname,
 {
 	struct sieve_storage_save_context *sctx;
 
+	sieve_storage_clear_error(storage);
+
 	if (scriptname != NULL) {
 		/* Validate script name */
 		if (!sieve_script_name_is_valid(scriptname)) {
@@ -1186,6 +1169,8 @@ int sieve_storage_save_continue(struct sieve_storage_save_context *sctx)
 	struct sieve_storage *storage = sctx->storage;
 	int ret;
 
+	sieve_storage_clear_error(storage);
+
 	i_assert(storage->v.save_continue != NULL);
 	ret = storage->v.save_continue(sctx);
 	if (ret < 0)
@@ -1198,6 +1183,8 @@ int sieve_storage_save_finish(struct sieve_storage_save_context *sctx)
 	struct sieve_storage *storage = sctx->storage;
 	int ret;
 
+	sieve_storage_clear_error(storage);
+
 	i_assert(!sctx->finished);
 	sctx->finished = TRUE;
 
@@ -1233,6 +1220,8 @@ sieve_storage_save_get_tempscript(struct sieve_storage_save_context *sctx)
 	if (sctx->scriptobject != NULL)
 		return sctx->scriptobject;
 
+	sieve_storage_clear_error(storage);
+
 	i_assert(storage->v.save_get_tempscript != NULL);
 	sctx->scriptobject = storage->v.save_get_tempscript(sctx);
 
@@ -1243,9 +1232,13 @@ sieve_storage_save_get_tempscript(struct sieve_storage_save_context *sctx)
 
 bool sieve_storage_save_will_activate(struct sieve_storage_save_context *sctx)
 {
+	struct sieve_storage *storage = sctx->storage;
+
 	if (sctx->scriptname == NULL)
 		return FALSE;
 
+	sieve_storage_clear_error(storage);
+
 	if (sctx->active_scriptname == NULL) {
 		const char *scriptname;
 
@@ -1275,6 +1268,7 @@ int sieve_storage_save_commit(struct sieve_storage_save_context **_sctx)
 
 	storage = sctx->storage;
 	scriptname = sctx->scriptname;
+	sieve_storage_clear_error(storage);
 
 	i_assert(!sctx->failed);
 	i_assert(sctx->finished);
@@ -1378,6 +1372,8 @@ int sieve_storage_save_as_active(struct sieve_storage *storage,
 	struct event *event;
 	int ret;
 
+	sieve_storage_clear_error(storage);
+
 	event = event_create(storage->event);
 	event_set_append_log_prefix(event, "active script: save: ");
 
@@ -1413,6 +1409,8 @@ int sieve_storage_save_as(struct sieve_storage *storage, struct istream *input,
 	struct event *event;
 	int ret;
 
+	sieve_storage_clear_error(storage);
+
 	event = sieve_storage_save_create_event(storage, name);
 
 	struct event_passthrough *e =
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index fd74d1929efeb6da0ca1dabeefcbf44a31dbf24a..2f7eb79e77ca3da8150bc062fba3f216faf3ed10 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -209,6 +209,8 @@ sieve_parse(struct sieve_script *script, struct sieve_error_handler *ehandler,
 	struct sieve_parser *parser;
 	struct sieve_ast *ast = NULL;
 
+	sieve_error_args_init(&error_code_r, NULL);
+
 	/* Parse */
 	parser = sieve_parser_create(script, ehandler, error_code_r);
 	if (parser == NULL)
@@ -221,12 +223,8 @@ sieve_parse(struct sieve_script *script, struct sieve_error_handler *ehandler,
 
 	sieve_parser_free(&parser);
 
-	if (error_code_r != NULL) {
-		if (ast == NULL)
-			*error_code_r = SIEVE_ERROR_NOT_VALID;
-		else
-			*error_code_r = SIEVE_ERROR_NONE;
-	}
+	if (ast == NULL)
+		*error_code_r = SIEVE_ERROR_NOT_VALID;
 	return ast;
 }
 
@@ -235,20 +233,18 @@ bool sieve_validate(struct sieve_ast *ast, struct sieve_error_handler *ehandler,
 		    enum sieve_error *error_code_r)
 {
 	bool result = TRUE;
-	struct sieve_validator *validator =
-		sieve_validator_create(ast, ehandler, flags);
+	struct sieve_validator *validator;
 
+	sieve_error_args_init(&error_code_r, NULL);
+
+	validator = sieve_validator_create(ast, ehandler, flags);
 	if (!sieve_validator_run(validator))
 		result = FALSE;
 
 	sieve_validator_free(&validator);
 
-	if (error_code_r != NULL) {
-		if (!result)
-			*error_code_r = SIEVE_ERROR_NOT_VALID;
-		else
-			*error_code_r = SIEVE_ERROR_NONE;
-	}
+	if (!result)
+		*error_code_r = SIEVE_ERROR_NOT_VALID;
 	return result;
 }
 
@@ -256,20 +252,18 @@ static struct sieve_binary *
 sieve_generate(struct sieve_ast *ast, struct sieve_error_handler *ehandler,
 	       enum sieve_compile_flags flags, enum sieve_error *error_code_r)
 {
-	struct sieve_generator *generator =
-		sieve_generator_create(ast, ehandler, flags);
+	struct sieve_generator *generator;
 	struct sieve_binary *sbin = NULL;
 
+	sieve_error_args_init(&error_code_r, NULL);
+
+	generator = sieve_generator_create(ast, ehandler, flags);
 	sbin = sieve_generator_run(generator, NULL);
 
 	sieve_generator_free(&generator);
 
-	if (error_code_r != NULL) {
-		if (sbin == NULL)
-			*error_code_r = SIEVE_ERROR_NOT_VALID;
-		else
-			*error_code_r = SIEVE_ERROR_NONE;
-	}
+	if (sbin == NULL)
+		*error_code_r = SIEVE_ERROR_NOT_VALID;
 	return sbin;
 }
 
@@ -285,20 +279,17 @@ int sieve_compile_script(struct sieve_script *script,
 {
 	struct sieve_ast *ast;
 	struct sieve_binary *sbin;
-	enum sieve_error error_code;
+	bool no_error_result = (error_code_r == NULL);
 
 	*sbin_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	/* Parse */
 	ast = sieve_parse(script, ehandler, error_code_r);
 	if (ast == NULL) {
 		switch (*error_code_r) {
 		case SIEVE_ERROR_NOT_FOUND:
-			if (error_code_r == NULL) {
+			if (no_error_result) {
 				sieve_error(ehandler, sieve_script_name(script),
 					    "script not found");
 			}
@@ -340,19 +331,19 @@ int sieve_compile(struct sieve_instance *svinst, const char *script_location,
 		  enum sieve_error *error_code_r)
 {
 	struct sieve_script *script;
-	enum sieve_error error_code;
+	bool no_error_result = (error_code_r == NULL);
 
 	*sbin_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	if (sieve_script_create_open(svinst, script_location, script_name,
 				     &script, error_code_r) < 0) {
 		switch (*error_code_r) {
 		case SIEVE_ERROR_NOT_FOUND:
-			sieve_error(ehandler, script_name, "script not found");
+			if (no_error_result) {
+				sieve_error(ehandler, script_name,
+					    "script not found");
+			}
 			break;
 		default:
 			sieve_internal_error(ehandler, script_name,
@@ -464,6 +455,7 @@ sieve_open_script_real(struct sieve_script *script,
 	if (ret <= 0) {
 		const char *path = sieve_binary_path(sbin);
 
+		i_assert(error != NULL);
 		if (path != NULL) {
 			e_debug(svinst->event,
 				"Script binary %s cannot be executed",
@@ -495,14 +487,10 @@ int sieve_open_script(struct sieve_script *script,
 		      struct sieve_binary **sbin_r,
 		      enum sieve_error *error_code_r)
 {
-	enum sieve_error error_code;
 	int ret;
 
 	*sbin_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	T_BEGIN {
 		ret = sieve_open_script_real(script, ehandler, flags,
@@ -518,14 +506,11 @@ int sieve_open(struct sieve_instance *svinst, const char *script_location,
 	       enum sieve_error *error_code_r)
 {
 	struct sieve_script *script;
-	enum sieve_error error_code;
+	bool no_error_result = (error_code_r == NULL);
 	int ret;
 
 	*sbin_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	/* First open the scriptfile itself */
 	if (sieve_script_create_open(svinst, script_location, script_name,
@@ -533,7 +518,10 @@ int sieve_open(struct sieve_instance *svinst, const char *script_location,
 		/* Failed */
 		switch (*error_code_r) {
 		case SIEVE_ERROR_NOT_FOUND:
-			sieve_error(ehandler, script_name, "script not found");
+			if (no_error_result) {
+				sieve_error(ehandler, script_name,
+					    "script not found");
+			}
 			break;
 		default:
 			sieve_internal_error(ehandler, script_name,
@@ -1019,6 +1007,25 @@ size_t sieve_max_script_size(struct sieve_instance *svinst)
 	"Internal error occurred. Refer to server log for more information."
 #define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
 
+void sieve_error_args_init(enum sieve_error **error_code_r,
+			   const char ***error_r)
+{
+	/* Dummies */
+	static enum sieve_error dummy_error_code = SIEVE_ERROR_NONE;
+	static const char *dummy_error = NULL;
+
+	if (error_code_r != NULL) {
+		if (*error_code_r == NULL)
+			*error_code_r = &dummy_error_code;
+		**error_code_r = SIEVE_ERROR_NONE;
+	}
+	if (error_r != NULL) {
+		if (*error_r == NULL)
+			*error_r = &dummy_error;
+		**error_r = NULL;
+	}
+}
+
 void sieve_error_create_internal(enum sieve_error *error_code_r,
 				 const char **error_r)
 {
diff --git a/src/lib-sieve/storage/file/sieve-file-storage-active.c b/src/lib-sieve/storage/file/sieve-file-storage-active.c
index bcc7456e1260ea82aa69847f415b3821adca36df..9893c35e8cbb0e20d3a7172d6ec29494e8f1aadf 100644
--- a/src/lib-sieve/storage/file/sieve-file-storage-active.c
+++ b/src/lib-sieve/storage/file/sieve-file-storage-active.c
@@ -243,6 +243,7 @@ int sieve_file_storage_active_script_open(struct sieve_storage *storage,
 	int ret;
 
 	*script_r = NULL;
+	sieve_storage_clear_error(storage);
 
 	/* Read the active link */
 	ret = sieve_file_storage_active_read_link(fstorage, &link);
diff --git a/src/lib-sieve/storage/file/sieve-file-storage.c b/src/lib-sieve/storage/file/sieve-file-storage.c
index cb48f1e9ad614c914c8890f87f533a56bd107630..72a0562f4e7554ff37d542211365ae88b2e09138 100644
--- a/src/lib-sieve/storage/file/sieve-file-storage.c
+++ b/src/lib-sieve/storage/file/sieve-file-storage.c
@@ -721,16 +721,12 @@ int sieve_file_storage_init_from_path(struct sieve_instance *svinst,
 {
 	struct sieve_storage *storage;
 	struct sieve_file_storage *fstorage;
-	enum sieve_error error_code;
 	int ret;
 
 	i_assert(path != NULL);
 
 	*fstorage_r = NULL;
-	if (error_code_r != NULL)
-		*error_code_r = SIEVE_ERROR_NONE;
-	else
-		error_code_r = &error_code;
+	sieve_error_args_init(&error_code_r, NULL);
 
 	ret = sieve_storage_alloc(svinst, NULL, &sieve_file_storage,
 				  "", flags, FALSE, &storage);