diff --git a/src/lib-sieve/sieve-storage-private.h b/src/lib-sieve/sieve-storage-private.h
index 70f5fc88dcec20c36f7119fb27cef286c48009c5..7dd007355c4faa440dfa1e6c5e4736170653f2a6 100644
--- a/src/lib-sieve/sieve-storage-private.h
+++ b/src/lib-sieve/sieve-storage-private.h
@@ -23,8 +23,7 @@ ARRAY_DEFINE_TYPE(sieve_storage_class, const struct sieve_storage *);
 struct sieve_storage_vfuncs {
 	struct sieve_storage *(*alloc)(void);
 	void (*destroy)(struct sieve_storage *storage);
-	int (*init)(struct sieve_storage *storage, const char *const *options,
-		    enum sieve_error *error_code_r);
+	int (*init)(struct sieve_storage *storage, const char *const *options);
 
 	int (*get_last_change)(struct sieve_storage *storage,
 			       time_t *last_change_r);
diff --git a/src/lib-sieve/sieve-storage.c b/src/lib-sieve/sieve-storage.c
index f9c9642108f134f9f0cc595c46e32a8c7951b36b..c4bde9f01b1c21a1a2ad40350ca084ab29fe4248 100644
--- a/src/lib-sieve/sieve-storage.c
+++ b/src/lib-sieve/sieve-storage.c
@@ -362,12 +362,12 @@ sieve_storage_init_real(struct sieve_instance *svinst, struct event *event,
 			event_add_str(event, "script_location",
 				      storage->location);
 
-			ret = storage_class->v.init(storage, options,
-						    error_code_r);
+			ret = storage_class->v.init(storage, options);
 			i_assert(ret <= 0);
 		}
 	} T_END;
 	if (ret < 0) {
+		*error_code_r = storage->error_code;
 		sieve_storage_unref(&storage);
 		return -1;
 	}
diff --git a/src/lib-sieve/storage/data/sieve-data-storage.c b/src/lib-sieve/storage/data/sieve-data-storage.c
index 73906c93d4526619fe9392455564e30f3b57db97..4f645532f4ad64a9ad3128e84ba4a9bf0c080e16 100644
--- a/src/lib-sieve/storage/data/sieve-data-storage.c
+++ b/src/lib-sieve/storage/data/sieve-data-storage.c
@@ -27,10 +27,8 @@ static struct sieve_storage *sieve_data_storage_alloc(void)
 
 static int
 sieve_data_storage_init(struct sieve_storage *storage ATTR_UNUSED,
-			const char *const *options ATTR_UNUSED,
-			enum sieve_error *error_code_r ATTR_UNUSED)
+			const char *const *options ATTR_UNUSED)
 {
-	*error_code_r = SIEVE_ERROR_NONE;
 	return 0;
 }
 
diff --git a/src/lib-sieve/storage/dict/sieve-dict-storage.c b/src/lib-sieve/storage/dict/sieve-dict-storage.c
index d94ebdd5a97f8c41d09d26177d4727577196f3bc..a8f48936d422bb20834e7d80fcad23400af15809 100644
--- a/src/lib-sieve/storage/dict/sieve-dict-storage.c
+++ b/src/lib-sieve/storage/dict/sieve-dict-storage.c
@@ -28,8 +28,7 @@ static struct sieve_storage *sieve_dict_storage_alloc(void)
 
 static int
 sieve_dict_storage_init(struct sieve_storage *storage,
-			const char *const *options,
-			enum sieve_error *error_code_r)
+			const char *const *options)
 {
 	struct sieve_dict_storage *dstorage =
 		container_of(storage, struct sieve_dict_storage, storage);
@@ -46,7 +45,6 @@ sieve_dict_storage_init(struct sieve_storage *storage,
 			} else {
 				sieve_storage_set_critical(
 					storage, "Invalid option '%s'", option);
-				*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 				return -1;
 			}
 
@@ -58,7 +56,6 @@ sieve_dict_storage_init(struct sieve_storage *storage,
 		sieve_storage_set_critical(
 			storage,
 			"BUG: Sieve interpreter is initialized without a base_dir");
-		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		return -1;
 	}
 
diff --git a/src/lib-sieve/storage/file/sieve-file-storage.c b/src/lib-sieve/storage/file/sieve-file-storage.c
index 72a0562f4e7554ff37d542211365ae88b2e09138..51cc7c4d17973fad235537825ddee49542f54bd4 100644
--- a/src/lib-sieve/storage/file/sieve-file-storage.c
+++ b/src/lib-sieve/storage/file/sieve-file-storage.c
@@ -47,8 +47,7 @@ sieve_file_storage_path_extend(struct sieve_file_storage *fstorage,
  */
 
 static int
-sieve_file_storage_stat(struct sieve_file_storage *fstorage, const char *path,
-			enum sieve_error *error_code_r)
+sieve_file_storage_stat(struct sieve_file_storage *fstorage, const char *path)
 {
 	struct sieve_storage *storage = &fstorage->storage;
 	struct stat st;
@@ -69,24 +68,22 @@ sieve_file_storage_stat(struct sieve_file_storage *fstorage, const char *path,
 			sieve_storage_set_critical(
 				storage, "t_abspath(%s) failed: %s", path,
 				error);
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 			break;
 		}
 		e_debug(storage->event, "Storage path '%s' not found", abspath);
 		sieve_storage_set_internal_error(storage); // should be overriden
-		*error_code_r = SIEVE_ERROR_NOT_FOUND;
+		storage->error_code = SIEVE_ERROR_NOT_FOUND;
 		break;
 	case EACCES:
 		sieve_storage_set_critical(
 			storage, "Failed to stat sieve storage path: %s",
 			eacces_error_get("stat", path));
-		*error_code_r = SIEVE_ERROR_NO_PERMISSION;
+		storage->error_code = SIEVE_ERROR_NO_PERMISSION;
 		break;
 	default:
 		sieve_storage_set_critical(
 			storage, "Failed to stat sieve storage path: "
 			"stat(%s) failed: %m", path);
-		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 		break;
 	}
 
@@ -141,11 +138,13 @@ mkdir_verify(struct sieve_storage *storage, const char *dir,
 		return 0;
 
 	if (errno == EACCES) {
-		e_error(storage->event,	"mkdir_verify: %s",
+		sieve_storage_set_critical(
+			storage, "mkdir_verify: %s",
 			eacces_error_get("stat", dir));
 		return -1;
 	} else if (errno != ENOENT) {
-		e_error(storage->event, "mkdir_verify: "
+		sieve_storage_set_critical(
+			storage, "mkdir_verify: "
 			"stat(%s) failed: %m", dir);
 		return -1;
 	}
@@ -159,15 +158,15 @@ mkdir_verify(struct sieve_storage *storage, const char *dir,
 	case EEXIST:
 		return 0;
 	case ENOENT:
-		e_error(storage->event,
+		sieve_storage_set_critical(storage,
 			"Storage was deleted while it was being created");
 		break;
 	case EACCES:
-		e_error(storage->event, "%s",
+		sieve_storage_set_critical(storage, "%s",
 			eacces_error_get_creating("mkdir_parents_chgrp", dir));
 		break;
 	default:
-		e_error(storage->event,
+		sieve_storage_set_critical(storage,
 			"mkdir_parents_chgrp(%s) failed: %m", dir);
 		break;
 	}
@@ -184,11 +183,13 @@ static int check_tmp(struct sieve_storage *storage, const char *path)
 		if (errno == ENOENT)
 			return 0;
 		if (errno == EACCES) {
-			e_error(storage->event, "check_tmp: %s",
+			sieve_storage_set_critical(storage,
+				"check_tmp: %s",
 				eacces_error_get("stat", path));
 			return -1;
 		}
-		e_error(storage->event, "check_tmp: stat(%s) failed: %m", path);
+		sieve_storage_set_critical(storage,
+			"check_tmp: stat(%s) failed: %m", path);
 		return -1;
 	}
 
@@ -220,8 +221,7 @@ static struct sieve_storage *sieve_file_storage_alloc(void)
 
 static int
 sieve_file_storage_get_full_path(struct sieve_file_storage *fstorage,
-				 const char **storage_path,
-				 enum sieve_error *error_code_r)
+				 const char **storage_path)
 {
 	struct sieve_storage *storage = &fstorage->storage;
 	struct sieve_instance *svinst = storage->svinst;
@@ -247,7 +247,6 @@ sieve_file_storage_get_full_path(struct sieve_file_storage *fstorage,
 				storage,
 				"Sieve storage path '%s' is relative to home directory, "
 				"but home directory is not available.", path);
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 			return -1;
 		}
 	}
@@ -257,8 +256,7 @@ sieve_file_storage_get_full_path(struct sieve_file_storage *fstorage,
 
 static int
 sieve_file_storage_get_full_active_path(struct sieve_file_storage *fstorage,
-					const char **active_path,
-					enum sieve_error *error_code_r)
+					const char **active_path)
 {
 	struct sieve_storage *storage = &fstorage->storage;
 	struct sieve_instance *svinst = storage->svinst;
@@ -282,7 +280,6 @@ sieve_file_storage_get_full_active_path(struct sieve_file_storage *fstorage,
 				storage,
 				"Sieve storage active script path '%s' is relative to home directory, "
 				"but home directory is not available.", path);
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 			return -1;
 		}
 	}
@@ -293,8 +290,7 @@ sieve_file_storage_get_full_active_path(struct sieve_file_storage *fstorage,
 static int
 sieve_file_storage_init_common(struct sieve_file_storage *fstorage,
 			       const char *active_path,
-			       const char *storage_path, bool exists,
-			       enum sieve_error *error_code_r)
+			       const char *storage_path, bool exists)
 {
 	struct sieve_storage *storage = &fstorage->storage;
 	const char *tmp_dir, *link_path, *active_fname, *storage_dir, *error;
@@ -307,8 +303,7 @@ sieve_file_storage_init_common(struct sieve_file_storage *fstorage,
 
 	/* Get active script path */
 
-	if (sieve_file_storage_get_full_active_path(fstorage, &active_path,
-						    error_code_r) < 0)
+	if (sieve_file_storage_get_full_active_path(fstorage, &active_path) < 0)
 		return -1;
 
 	/* Get the filename for the active script link */
@@ -333,16 +328,14 @@ sieve_file_storage_init_common(struct sieve_file_storage *fstorage,
 				"Path to %sscript must include the filename (path=%s)",
 				(storage_path != NULL ? "active link/" : ""),
 				active_path);
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 			return -1;
 		}
 
 		if (t_realpath(active_dir, &active_dir, &error) < 0) {
 			if (errno != ENOENT) {
-				e_error(storage->event,
+				sieve_storage_set_critical(storage,
 					"Failed to normalize active script directory "
 					"(path=%s): %s", active_dir, error);
-				*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 				return -1;
 			}
 			e_debug(storage->event,
@@ -372,7 +365,6 @@ sieve_file_storage_init_common(struct sieve_file_storage *fstorage,
 		if ((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) != 0) {
 			sieve_storage_set_critical(storage,
 				"Storage path cannot be empty for write access");
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 			return -1;
 		}
 
@@ -440,34 +432,28 @@ sieve_file_storage_init_common(struct sieve_file_storage *fstorage,
 
 		/* Try to find and clean up tmp dir */
 		ret = check_tmp(storage, tmp_dir);
-		if (ret < 0) {
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		if (ret < 0)
 			return -1;
-		}
 
 		/* Auto-create if necessary */
 		if (ret == 0 && mkdir_verify(storage, tmp_dir, dir_create_mode,
 					     file_create_gid,
-					     file_create_gid_origin) < 0) {
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+					     file_create_gid_origin) < 0)
 			return -1;
-		}
 
 		fstorage->dir_create_mode = dir_create_mode;
 		fstorage->file_create_mode = file_create_mode;
 		fstorage->file_create_gid = file_create_gid;
 	}
 
-	if (!exists && sieve_file_storage_stat(fstorage, storage_path,
-					       error_code_r) < 0)
+	if (!exists && sieve_file_storage_stat(fstorage, storage_path) < 0)
 		return -1;
 
 	if (have_link) {
 		if (t_realpath(storage_path, &storage_path, &error) < 0) {
-			e_error(storage->event,
+			sieve_storage_set_critical(storage,
 				"Failed to normalize storage path (path=%s): %s",
 				storage_path, error);
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 			return -1;
 		}
 		if (active_path != NULL && *active_path != '\0') {
@@ -494,8 +480,7 @@ sieve_file_storage_init_common(struct sieve_file_storage *fstorage,
 
 static int
 sieve_file_storage_init(struct sieve_storage *storage,
-			const char *const *options,
-			enum sieve_error *error_code_r)
+			const char *const *options)
 {
 	struct sieve_file_storage *fstorage =
 		container_of(storage, struct sieve_file_storage, storage);
@@ -513,7 +498,6 @@ sieve_file_storage_init(struct sieve_storage *storage,
 			} else {
 				sieve_storage_set_critical(
 					storage, "Invalid option '%s'", option);
-				*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 				return -1;
 			}
 
@@ -523,16 +507,14 @@ sieve_file_storage_init(struct sieve_storage *storage,
 
 	/* Get full storage path */
 
-	if (sieve_file_storage_get_full_path(fstorage, &storage_path,
-					     error_code_r) < 0)
+	if (sieve_file_storage_get_full_path(fstorage, &storage_path) < 0)
 		return -1;
 
 	/* Stat storage directory */
 
 	if (storage_path != NULL && *storage_path != '\0') {
-		if (sieve_file_storage_stat(fstorage, storage_path,
-					    error_code_r) < 0) {
-			if (*error_code_r != SIEVE_ERROR_NOT_FOUND)
+		if (sieve_file_storage_stat(fstorage, storage_path) < 0) {
+			if (storage->error_code != SIEVE_ERROR_NOT_FOUND)
 				return -1;
 			if ((storage->flags & SIEVE_STORAGE_FLAG_READWRITE) == 0) {
 				/* For backwards compatibility, recognize when
@@ -542,12 +524,10 @@ sieve_file_storage_init(struct sieve_storage *storage,
 				if (active_path == NULL || *active_path == '\0')
 					return -1;
 				if (sieve_file_storage_get_full_active_path(
-					fstorage, &active_path,
-					error_code_r) < 0)
+					fstorage, &active_path) < 0)
 					return -1;
-				if (sieve_file_storage_stat(
-					fstorage, active_path,
-					error_code_r) < 0)
+				if (sieve_file_storage_stat(fstorage,
+							    active_path) < 0)
 					return -1;
 				if (!S_ISREG(fstorage->lnk_st.st_mode))
 					return -1;
@@ -566,7 +546,6 @@ sieve_file_storage_init(struct sieve_storage *storage,
 					sieve_storage_set_critical(storage,
 						"Sieve storage path '%s' is not a directory, "
 						"but it is to be opened for write access", storage_path);
-					*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 					return -1;
 				}
 				if (active_path != NULL && *active_path != '\0') {
@@ -593,8 +572,7 @@ sieve_file_storage_init(struct sieve_storage *storage,
 	}
 
 	return sieve_file_storage_init_common(fstorage, active_path,
-					      storage_path, exists,
-					      error_code_r);
+					      storage_path, exists);
 }
 
 static void
@@ -642,9 +620,8 @@ sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 
 	if (storage_path != NULL && *storage_path != '\0') {
 		/* Got something: stat it */
-		if (sieve_file_storage_stat(fstorage, storage_path,
-					    error_code_r) < 0) {
-			if (*error_code_r != SIEVE_ERROR_NOT_FOUND) {
+		if (sieve_file_storage_stat(fstorage, storage_path) < 0) {
+			if (storage->error_code != SIEVE_ERROR_NOT_FOUND) {
 				/* Error */
 				return -1;
 			}
@@ -659,7 +636,7 @@ sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 		sieve_storage_set_critical(storage,
 			"Could not find storage root directory for write access; "
 			"path was left unconfigured and autodetection failed");
-		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		*error_code_r = storage->error_code;
 		return -1;
 	}
 
@@ -681,8 +658,10 @@ sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 		storage_path = NULL;
 
 	if (sieve_file_storage_init_common(fstorage, active_path, storage_path,
-					   exists, error_code_r) < 0)
+					   exists) < 0) {
+		*error_code_r = storage->error_code;
 		return -1;
+	}
 	return 0;
 }
 
@@ -735,9 +714,10 @@ int sieve_file_storage_init_from_path(struct sieve_instance *svinst,
 
 	T_BEGIN {
 		ret = sieve_file_storage_init_common(fstorage, path, NULL,
-						     FALSE, error_code_r);
+						     FALSE);
 	} T_END;
 	if (ret < 0) {
+		*error_code_r = storage->error_code;
 		sieve_storage_unref(&storage);
 		return -1;
 	}
diff --git a/src/lib-sieve/storage/ldap/sieve-ldap-storage.c b/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
index a0974002e03d8b01657aece1d4cf9381f75b5574..8a7e0980cd1fa605fee9ac1924a70dd668898340 100644
--- a/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
+++ b/src/lib-sieve/storage/ldap/sieve-ldap-storage.c
@@ -42,8 +42,7 @@ static struct sieve_storage *sieve_ldap_storage_alloc(void)
 
 static int
 sieve_ldap_storage_init(struct sieve_storage *storage,
-			const char *const *options,
-			enum sieve_error *error_code_r)
+			const char *const *options)
 {
 	struct sieve_ldap_storage *lstorage =
 		container_of(storage, struct sieve_ldap_storage, storage);
@@ -60,7 +59,6 @@ sieve_ldap_storage_init(struct sieve_storage *storage,
 			} else {
 				sieve_storage_set_critical(
 					storage, "Invalid option '%s'", option);
-				*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
 				return -1;
 			}