diff --git a/src/lib-sieve/plugins/include/ext-include-common.c b/src/lib-sieve/plugins/include/ext-include-common.c
index bb66aa5e08fd61ccb1ca289e920eb0c6c0fe2dce..6f9c2fddeae95c194af25d1abf870cfe22dce901 100644
--- a/src/lib-sieve/plugins/include/ext-include-common.c
+++ b/src/lib-sieve/plugins/include/ext-include-common.c
@@ -163,7 +163,8 @@ ext_include_open_script_global(struct sieve_instance *svinst,
 	}
 
 	return sieve_script_create_open(svinst, extctx->global_location,
-					script_name, script_r, error_code_r);
+					script_name,
+					script_r, error_code_r, NULL);
 }
 
 int ext_include_open_script(const struct sieve_extension *ext,
diff --git a/src/lib-sieve/sieve-script.c b/src/lib-sieve/sieve-script.c
index efdde6369d075fd19efa4e4b658124aba9753794..d2006cce48fb20c8e17b08ff52e15e07b2ee7dc5 100644
--- a/src/lib-sieve/sieve-script.c
+++ b/src/lib-sieve/sieve-script.c
@@ -123,15 +123,16 @@ static int
 sieve_script_create_common(struct sieve_instance *svinst,
 			   const char *location, const char *name, bool open,
 			   struct sieve_script **script_r,
-			   enum sieve_error *error_code_r)
+			   enum sieve_error *error_code_r,
+			   const char **error_r)
 {
 	struct sieve_storage_sequence *sseq;
 
 	*script_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	if (sieve_storage_sequence_create(svinst, svinst->event, location,
-					  &sseq, error_code_r) < 0)
+					  &sseq, error_code_r, error_r) < 0)
 		return -1;
 
 	struct sieve_storage *storage;
@@ -141,8 +142,9 @@ sieve_script_create_common(struct sieve_instance *svinst,
 	/* Find the first storage that has the script */
 	for (;;) {
 		*error_code_r = SIEVE_ERROR_NONE;
+		*error_r = NULL;
 		ret = sieve_storage_sequence_next(sseq, &storage,
-						  error_code_r);
+						  error_code_r, error_r);
 		if (ret == 0)
 			break;
 		if (ret < 0) {
@@ -157,6 +159,8 @@ sieve_script_create_common(struct sieve_instance *svinst,
 				sieve_storage_unref(&storage);
 				continue;
 			}
+			*error_r = sieve_storage_get_last_error(
+				storage, error_code_r);
 			ret = -1;
 		} else {
 			ret = 1;
@@ -164,6 +168,8 @@ sieve_script_create_common(struct sieve_instance *svinst,
 		sieve_storage_unref(&storage);
 		if (ret > 0 && open &&
 		    sieve_script_open(script, error_code_r) < 0) {
+			*error_r = sieve_storage_get_last_error(
+				storage, error_code_r);
 			sieve_script_unref(&script);
 			if (*error_code_r == SIEVE_ERROR_NOT_FOUND)
 				continue;
@@ -177,7 +183,8 @@ sieve_script_create_common(struct sieve_instance *svinst,
 		ret = 0;
 	} else if (ret == 0) {
 		i_assert(*error_code_r == SIEVE_ERROR_NONE);
-		*error_code_r = SIEVE_ERROR_NOT_FOUND;
+		sieve_error_create_script_not_found(
+			name, error_code_r, error_r);
 		ret = -1;
 	}
 
@@ -188,10 +195,10 @@ sieve_script_create_common(struct sieve_instance *svinst,
 int sieve_script_create(struct sieve_instance *svinst,
 			const char *location, const char *name,
 			struct sieve_script **script_r,
-			enum sieve_error *error_code_r)
+			enum sieve_error *error_code_r, const char **error_r)
 {
 	return sieve_script_create_common(svinst, location, name, FALSE,
-					  script_r, error_code_r);
+					  script_r, error_code_r, error_r);
 }
 
 void sieve_script_ref(struct sieve_script *script)
@@ -273,19 +280,24 @@ int sieve_script_open_as(struct sieve_script *script, const char *name,
 int sieve_script_create_open(struct sieve_instance *svinst,
 			     const char *location, const char *name,
 			     struct sieve_script **script_r,
-			     enum sieve_error *error_code_r)
+			     enum sieve_error *error_code_r,
+			     const char **error_r)
 {
 	return sieve_script_create_common(svinst, location, name, TRUE,
-					  script_r, error_code_r);
+					  script_r, error_code_r, error_r);
 }
 
-int sieve_script_check(struct sieve_instance *svinst, const char *location,
-		       const char *name, enum sieve_error *error_code_r)
+int sieve_script_check(struct sieve_instance *svinst,
+		       const char *location, const char *name,
+		       enum sieve_error *error_code_r, const char **error_r)
 {
 	struct sieve_script *script;
+	enum sieve_error error_code;
+
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	if (sieve_script_create_open(svinst, location, name,
-				     &script, error_code_r) < 0)
+				     &script, &error_code, error_r) < 0)
 		return (*error_code_r == SIEVE_ERROR_NOT_FOUND ? 0 : -1);
 
 	sieve_script_unref(&script);
@@ -551,7 +563,7 @@ bool sieve_script_binary_dump_metadata(struct sieve_script *script,
 	if (script == NULL) {
 		adhoc_script = NULL;
 		if (sieve_script_create(svinst, str_c(location),
-					NULL, &script, NULL) == 0)
+					NULL, &script, NULL, NULL) == 0)
 			adhoc_script = script;
 	}
 
@@ -1004,16 +1016,18 @@ const char *sieve_script_get_last_error_lcase(struct sieve_script *script)
 int sieve_script_sequence_create(struct sieve_instance *svinst,
 				 const char *location,
 				 struct sieve_script_sequence **sseq_r,
-				 enum sieve_error *error_code_r)
+				 enum sieve_error *error_code_r,
+				 const char **error_r)
 {
 	struct sieve_storage_sequence *storage_seq;
 	struct sieve_script_sequence *sseq;
 
 	*sseq_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	if (sieve_storage_sequence_create(svinst, svinst->event, location,
-					  &storage_seq, error_code_r) < 0)
+					  &storage_seq,
+					  error_code_r, error_r) < 0)
 		return -1;
 
 	sseq = i_new(struct sieve_script_sequence, 1);
@@ -1025,13 +1039,15 @@ int sieve_script_sequence_create(struct sieve_instance *svinst,
 
 static int
 sieve_script_sequence_init_storage(struct sieve_script_sequence *sseq,
-				   enum sieve_error *error_code_r)
+				   enum sieve_error *error_code_r,
+				   const char **error_r)
 {
 	int ret;
 
 	while (sseq->storage == NULL) {
 		ret = sieve_storage_sequence_next(sseq->storage_seq,
-						  &sseq->storage, error_code_r);
+						  &sseq->storage,
+						  error_code_r, error_r);
 		if (ret == 0)
 			return 0;
 		if (ret < 0) {
@@ -1044,8 +1060,10 @@ sieve_script_sequence_init_storage(struct sieve_script_sequence *sseq,
 
 		i_assert(storage->v.script_sequence_init != NULL);
 		*error_code_r = SIEVE_ERROR_NONE;
+		*error_r = NULL;
 		ret = storage->v.script_sequence_init(sseq);
 		*error_code_r = storage->error_code;
+		*error_r = storage->error;
 		sieve_storage_unref(&sseq->storage);
 		if (ret < 0 && *error_code_r != SIEVE_ERROR_NOT_FOUND)
 			return -1;
@@ -1067,25 +1085,32 @@ sieve_script_sequence_deinit_storage(struct sieve_script_sequence *sseq)
 
 int sieve_script_sequence_next(struct sieve_script_sequence *sseq,
 			       struct sieve_script **script_r,
-			       enum sieve_error *error_code_r)
+			       enum sieve_error *error_code_r,
+			       const char **error_r)
 {
 	int ret;
 
 	*script_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
-	while ((ret = sieve_script_sequence_init_storage(sseq, error_code_r)) > 0) {
+	while ((ret = sieve_script_sequence_init_storage(
+			sseq, error_code_r, error_r)) > 0) {
 		struct sieve_storage *storage =	sseq->storage;
 
 		i_assert(storage->v.script_sequence_next != NULL);
 		sieve_storage_clear_error(storage);
 		ret = storage->v.script_sequence_next(sseq, script_r);
-		*error_code_r = storage->error_code;
 		if (ret > 0)
 			break;
 
-		if (ret < 0 && *error_code_r == SIEVE_ERROR_NOT_FOUND)
-			ret = 0;
+		if (ret < 0) {
+			if (*error_code_r == SIEVE_ERROR_NOT_FOUND)
+				ret = 0;
+			else {
+				*error_code_r = storage->error_code;
+				*error_r = t_strdup(storage->error);
+			}
+		}
 
 		sieve_script_sequence_deinit_storage(sseq);
 		if (ret < 0)
diff --git a/src/lib-sieve/sieve-script.h b/src/lib-sieve/sieve-script.h
index 1d6be3f3db48ce40a1e10ace05a1427576165563..798ebafef9017b5ed0ac1dbc40cecf57dd0c14a1 100644
--- a/src/lib-sieve/sieve-script.h
+++ b/src/lib-sieve/sieve-script.h
@@ -38,7 +38,7 @@ ARRAY_DEFINE_TYPE(sieve_script, struct sieve_script *);
 int sieve_script_create(struct sieve_instance *svinst,
 			const char *location, const char *name,
 			struct sieve_script **script_r,
-			enum sieve_error *error_code_r);
+			enum sieve_error *error_code_r, const char **error_r);
 
 void sieve_script_ref(struct sieve_script *script);
 void sieve_script_unref(struct sieve_script **script);
@@ -51,9 +51,11 @@ int sieve_script_open_as(struct sieve_script *script, const char *name,
 int sieve_script_create_open(struct sieve_instance *svinst,
 			     const char *location, const char *name,
 			     struct sieve_script **script_r,
-			     enum sieve_error *error_code_r);
-int sieve_script_check(struct sieve_instance *svinst, const char *location,
-		       const char *name, enum sieve_error *error_code_r);
+			     enum sieve_error *error_code_r,
+			     const char **error_r);
+int sieve_script_check(struct sieve_instance *svinst,
+		       const char *location, const char *name,
+		       enum sieve_error *error_code_r, const char **error_r);
 
 /*
  * Data script
@@ -156,10 +158,12 @@ struct sieve_script_sequence;
 int sieve_script_sequence_create(struct sieve_instance *svinst,
 				 const char *location,
 				 struct sieve_script_sequence **sseq_r,
-				 enum sieve_error *error_code_r);
+				 enum sieve_error *error_code_r,
+				 const char **error_r);
 int sieve_script_sequence_next(struct sieve_script_sequence *sseq,
 			       struct sieve_script **script_r,
-			       enum sieve_error *error_code_r);
+			       enum sieve_error *error_code_r,
+			       const char **error_r);
 void sieve_script_sequence_free(struct sieve_script_sequence **_seq);
 
 #endif
diff --git a/src/lib-sieve/sieve-storage-private.h b/src/lib-sieve/sieve-storage-private.h
index 6b1a45796e6c0a9e7f5964dec4757915534d4205..eb52e8bafe8ee064a0f84d300c2f8fde598bd044 100644
--- a/src/lib-sieve/sieve-storage-private.h
+++ b/src/lib-sieve/sieve-storage-private.h
@@ -122,7 +122,7 @@ int sieve_storage_alloc(struct sieve_instance *svinst, struct event *event,
 			const struct sieve_storage *storage_class,
 			const char *data, enum sieve_storage_flags flags,
 			bool main, struct sieve_storage **storage_r,
-			enum sieve_error *error_code_r);
+			enum sieve_error *error_code_r, const char **error_r);
 
 int sieve_storage_setup_bin_path(struct sieve_storage *storage, mode_t mode);
 
@@ -220,7 +220,8 @@ int sieve_file_storage_init_default(struct sieve_instance *svinst,
 				    const char *active_path,
 				    enum sieve_storage_flags flags,
 				    struct sieve_storage **storage_r,
-				    enum sieve_error *error_code_r);
+				    enum sieve_error *error_code_r,
+				    const char **error_r);
 
 /* dict */
 
diff --git a/src/lib-sieve/sieve-storage.c b/src/lib-sieve/sieve-storage.c
index ea921ccf93cbcf495cddf3e0b1fcada1931a8354..95d46f992865903dd2dd2e7ce6655117ccc7621c 100644
--- a/src/lib-sieve/sieve-storage.c
+++ b/src/lib-sieve/sieve-storage.c
@@ -297,7 +297,8 @@ sieve_storage_alloc_from_class(struct sieve_instance *svinst,
 			       const char *data,
 			       enum sieve_storage_flags flags,
 			       struct sieve_storage **storage_r,
-			       enum sieve_error *error_code_r)
+			       enum sieve_error *error_code_r,
+			       const char **error_r)
 {
 	struct sieve_storage *storage;
 
@@ -305,20 +306,21 @@ sieve_storage_alloc_from_class(struct sieve_instance *svinst,
 
 	if (storage_class->v.alloc == NULL) {
 		e_error(event, "Support not compiled in for this driver");
-		*error_code_r = SIEVE_ERROR_NOT_FOUND;
+		sieve_error_create_script_not_found(
+			NULL, error_code_r, error_r);
 		return -1;
 	}
 
 	if ((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) != 0 &&
 	    !storage_class->allows_synchronization) {
 		e_error(event, "Storage does not support synchronization");
-		*error_code_r = SIEVE_ERROR_NOT_POSSIBLE;
+		sieve_error_create_internal(error_code_r, error_r);
 		return -1;
 	}
 	if ((flags & SIEVE_STORAGE_FLAG_READWRITE) != 0 &&
 	    storage_class->v.save_init == NULL) {
 		e_error(event, "Storage does not support write access");
-		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		sieve_error_create_internal(error_code_r, error_r);
 		return -1;
 	}
 
@@ -340,13 +342,13 @@ int sieve_storage_alloc(struct sieve_instance *svinst, struct event *event,
 			const struct sieve_storage *storage_class,
 			const char *data, enum sieve_storage_flags flags,
 			bool main, struct sieve_storage **storage_r,
-			enum sieve_error *error_code_r)
+			enum sieve_error *error_code_r, const char **error_r)
 {
 	struct sieve_storage *storage;
 	int ret;
 
 	*storage_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	if (event != NULL)
 		event_ref(event);
@@ -362,7 +364,7 @@ int sieve_storage_alloc(struct sieve_instance *svinst, struct event *event,
 
 	ret = sieve_storage_alloc_from_class(svinst, event, storage_class,
 					     data, flags,
-					     &storage, error_code_r);
+					     &storage, error_code_r, error_r);
 	if (ret == 0)
 		storage->main_storage = main;
 
@@ -378,7 +380,7 @@ sieve_storage_init_real(struct sieve_instance *svinst, struct event *event,
 			const char *data,
 			enum sieve_storage_flags flags, bool main,
 			struct sieve_storage **storage_r,
-			enum sieve_error *error_code_r)
+			enum sieve_error *error_code_r, const char **error_r)
 {
 	struct sieve_storage *storage;
 	struct event *driver_event;
@@ -389,7 +391,8 @@ sieve_storage_init_real(struct sieve_instance *svinst, struct event *event,
 	driver_event = sieve_storage_create_driver_event(
 		event, storage_class->driver_name);
 	ret = sieve_storage_alloc(svinst, driver_event, storage_class,
-				  data, flags, main, &storage, error_code_r);
+				  data, flags, main, &storage,
+				  error_code_r, error_r);
 	event_unref(&driver_event);
 	if (ret < 0)
 		return -1;
@@ -399,7 +402,7 @@ sieve_storage_init_real(struct sieve_instance *svinst, struct event *event,
 	T_BEGIN {
 		if (sieve_storage_data_parse(storage, data,
 					     &location, &options) < 0) {
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+			sieve_error_create_internal(error_code_r, error_r);
 			ret = -1;
 		} else {
 			storage->location = p_strdup(storage->pool, location);
@@ -413,6 +416,7 @@ sieve_storage_init_real(struct sieve_instance *svinst, struct event *event,
 	} T_END;
 	if (ret < 0) {
 		*error_code_r = storage->error_code;
+		*error_r = t_strdup(storage->error);
 		sieve_storage_unref(&storage);
 		return -1;
 	}
@@ -425,7 +429,7 @@ sieve_storage_init(struct sieve_instance *svinst, struct event *event_parent,
 		   const struct sieve_storage *storage_class, const char *data,
 		   enum sieve_storage_flags flags, bool main,
 		   struct sieve_storage **storage_r,
-		   enum sieve_error *error_code_r)
+		   enum sieve_error *error_code_r, const char **error_r)
 {
 	struct event *event;
 	int ret;
@@ -436,7 +440,7 @@ sieve_storage_init(struct sieve_instance *svinst, struct event *event_parent,
 
 	ret = sieve_storage_init_real(svinst, event, storage_class,
 				      data, flags, main,
-				      storage_r, error_code_r);
+				      storage_r, error_code_r, error_r);
 
 	event_unref(&event);
 
@@ -447,7 +451,7 @@ int sieve_storage_create(struct sieve_instance *svinst, struct event *event,
 			 const char *location,
 			 enum sieve_storage_flags flags,
 			 struct sieve_storage **storage_r,
-			 enum sieve_error *error_code_r)
+			 enum sieve_error *error_code_r, const char **error_r)
 {
 	const struct sieve_storage *storage_class;
 	const char *data;
@@ -457,12 +461,12 @@ int sieve_storage_create(struct sieve_instance *svinst, struct event *event,
 	i_assert((flags & SIEVE_STORAGE_FLAG_SYNCHRONIZING) == 0);
 
 	*storage_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	data = location;
 	if ((ret = sieve_storage_driver_parse(svinst, &data,
 					      &storage_class)) < 0) {
-		*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+		sieve_error_create_internal(error_code_r, error_r);
 		return -1;
 	}
 
@@ -471,7 +475,7 @@ int sieve_storage_create(struct sieve_instance *svinst, struct event *event,
 
 	return sieve_storage_init(svinst, event, storage_class,
 				  data, flags, FALSE,
-				  storage_r, error_code_r);
+				  storage_r, error_code_r, error_r);
 }
 
 static int
@@ -479,22 +483,24 @@ sieve_storage_create_default(struct sieve_instance *svinst,
 			     const char *location,
 			     enum sieve_storage_flags flags,
 			     struct sieve_storage **storage_r,
-			     enum sieve_error *error_code_r)
+			     enum sieve_error *error_code_r,
+			     const char **error_r)
 {
 	struct sieve_storage *storage;
 	enum sieve_error error_code;
 	int ret;
 
 	*storage_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	if (location == NULL) {
-		*error_code_r = SIEVE_ERROR_NOT_FOUND;
+		sieve_error_create_script_not_found(
+			NULL, error_code_r, error_r);
 		return -1;
 	}
 
 	ret = sieve_storage_create(svinst, svinst->event, location, flags,
-				   &storage, &error_code);
+				   &storage, &error_code, error_r);
 	if (ret >= 0) {
 		storage->is_default = TRUE;
 	} else {
@@ -526,10 +532,11 @@ sieve_storage_create_default(struct sieve_instance *svinst,
 static int
 sieve_storage_create_default_for(struct sieve_storage *storage,
 				 struct sieve_storage **storage_r,
-				 enum sieve_error *error_code_r)
+				 enum sieve_error *error_code_r,
+				 const char **error_r)
 {
 	*storage_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	if (storage->default_storage != NULL) {
 		sieve_storage_ref(storage->default_storage);
@@ -540,19 +547,21 @@ sieve_storage_create_default_for(struct sieve_storage *storage,
 	if (storage->default_name == NULL) {
 		sieve_storage_set_not_found_error(storage, NULL);
 		*error_code_r = storage->error_code;
+		*error_r = storage->error;
 		return -1;
 	}
 
 	struct sieve_instance *svinst = storage->svinst;
 	enum sieve_error error_code;
+	const char *error;
 
 	i_assert(storage->default_storage_for == NULL);
 	if (sieve_storage_create_default(svinst, storage->default_location, 0,
 					 &storage->default_storage,
-					 &error_code) < 0) {
-		sieve_storage_set_error(storage, error_code,
-					"Failed to access default script");
+					 &error_code, &error) < 0) {
+		sieve_storage_set_error(storage, error_code, "%s", error);
 		*error_code_r = storage->error_code;
+		*error_r = storage->error;
 		return -1;
 	}
 
@@ -593,7 +602,7 @@ sieve_storage_do_create_personal(struct sieve_instance *svinst,
 		data = set_sieve;
 		if ((ret = sieve_storage_driver_parse(svinst, &data,
 						      &sieve_class)) < 0) {
-			*error_code_r = SIEVE_ERROR_TEMP_FAILURE;
+			sieve_error_create_internal(error_code_r, NULL);
 			return -1;
 		}
 
@@ -601,7 +610,8 @@ sieve_storage_do_create_personal(struct sieve_instance *svinst,
 			/* The normal case: explicit driver name */
 			if (sieve_storage_init(svinst, svinst->event,
 					       sieve_class, data, flags, TRUE,
-					       &storage, error_code_r) < 0)
+					       &storage, error_code_r,
+					       NULL) < 0)
 				return -1;
 		}
 
@@ -609,8 +619,10 @@ sieve_storage_do_create_personal(struct sieve_instance *svinst,
 	}
 
 	if (storage == NULL) {
+		const char *error;
 		if (sieve_file_storage_init_default(svinst, set_sieve, flags,
-						    &storage, error_code_r) < 0)
+						    &storage, error_code_r,
+						    &error) < 0)
 			return -1;
 		i_assert(storage != NULL);
 	}
@@ -713,8 +725,9 @@ int sieve_storage_create_personal(struct sieve_instance *svinst,
 				set_default);
 		}
 
-		ret = sieve_storage_create_default(svinst, set_default, 0,
-						   &storage, error_code_r);
+		ret = sieve_storage_create_default(svinst, set_default,
+						   0, &storage,
+						   error_code_r, NULL);
 	}
 	*storage_r = storage;
 	return ret;
@@ -913,7 +926,7 @@ sieve_storage_get_default_script(struct sieve_storage *storage,
 	/* Failed; try using default script location
 	   (not for temporary failures, read/write access, or dsync) */
 	ret = sieve_storage_create_default_for(storage, &def_storage,
-					       error_code_r);
+					       error_code_r, NULL);
 	if (ret < 0)
 		return -1;
 
@@ -1058,7 +1071,8 @@ sieve_storage_active_script_do_get_name(struct sieve_storage *storage,
 
 	/* Failed; try using default script location
 	   (not for temporary failures, read/write access, or dsync) */
-	ret = sieve_storage_create_default_for(storage, &def_storage, NULL);
+	ret = sieve_storage_create_default_for(storage, &def_storage,
+					       NULL, NULL);
 	if (ret < 0)
 		return -1;
 
@@ -1121,7 +1135,7 @@ int sieve_storage_active_script_open(struct sieve_storage *storage,
 
 	/* Try default script location */
 	ret = sieve_storage_create_default_for(storage, &def_storage,
-					       error_code_r);
+					       error_code_r, NULL);
 	if (ret < 0)
 		return -1;
 
@@ -1202,7 +1216,7 @@ int sieve_storage_list_init(struct sieve_storage *storage,
 	enum sieve_error error_code;
 
 	if (sieve_storage_create_default_for(storage, &lctx->def_storage,
-					     &error_code) < 0 &&
+					     &error_code, NULL) < 0 &&
 	    error_code != SIEVE_ERROR_NOT_FOUND)
 		return -1;
 
@@ -1479,7 +1493,7 @@ sieve_storage_save_is_activating_default(
 	int ret = 0;
 
 	if (sieve_storage_create_default_for(storage, &def_storage,
-					     &error_code) < 0) {
+					     &error_code, NULL) < 0) {
 		if (error_code == SIEVE_ERROR_NOT_FOUND)
 			return 0;
 		return -1;
@@ -1851,10 +1865,11 @@ int sieve_storage_sequence_create(struct sieve_instance *svinst,
 				  struct event *event_parent,
 				  const char *location,
 				  struct sieve_storage_sequence **sseq_r,
-				  enum sieve_error *error_code_r)
+				  enum sieve_error *error_code_r,
+				  const char **error_r)
 {
 	*sseq_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	struct sieve_storage_sequence *sseq;
 
@@ -1871,19 +1886,20 @@ int sieve_storage_sequence_create(struct sieve_instance *svinst,
 
 int sieve_storage_sequence_next(struct sieve_storage_sequence *sseq,
 				struct sieve_storage **storage_r,
-				enum sieve_error *error_code_r)
+				enum sieve_error *error_code_r,
+				const char **error_r)
 {
 	struct sieve_instance *svinst = sseq->svinst;
 
 	*storage_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	if (sseq->done)
 		return 0;
 	sseq->done = TRUE;
 
 	if (sieve_storage_create(svinst, sseq->event_parent, sseq->location, 0,
-				 storage_r, error_code_r) < 0)
+				 storage_r, error_code_r, error_r) < 0)
 		return -1;
 	return 1;
 }
diff --git a/src/lib-sieve/sieve-storage.h b/src/lib-sieve/sieve-storage.h
index 9ba836f5f832e4595c9746c055458fb1e23870c8..4ffd280e308e26c95e17ca6356242ea54ab1fdc2 100644
--- a/src/lib-sieve/sieve-storage.h
+++ b/src/lib-sieve/sieve-storage.h
@@ -33,7 +33,7 @@ int sieve_storage_create(struct sieve_instance *svinst, struct event *event,
 			 const char *location,
 			 enum sieve_storage_flags flags,
 			 struct sieve_storage **storage_r,
-			 enum sieve_error *error_code_r);
+			 enum sieve_error *error_code_r, const char **error_r);
 int sieve_storage_create_personal(struct sieve_instance *svinst,
 				  struct mail_user *user,
 				  enum sieve_storage_flags flags,
@@ -192,10 +192,12 @@ int sieve_storage_sequence_create(struct sieve_instance *svinst,
 				  struct event *event_parent,
 				  const char *location,
 				  struct sieve_storage_sequence **sseq_r,
-				  enum sieve_error *error_code_r);
+				  enum sieve_error *error_code_r,
+				  const char **error_r);
 int sieve_storage_sequence_next(struct sieve_storage_sequence *sseq,
 				struct sieve_storage **storage_r,
-				enum sieve_error *error_code_r);
+				enum sieve_error *error_code_r,
+				const char **error_r);
 void sieve_storage_sequence_free(struct sieve_storage_sequence **_sseq);
 
 #endif
diff --git a/src/lib-sieve/sieve.c b/src/lib-sieve/sieve.c
index e0dcdf2450e348478957d508a2002fa3c6d7ce70..70cd01c8509396843a51c632ee13d1ddb50f2892 100644
--- a/src/lib-sieve/sieve.c
+++ b/src/lib-sieve/sieve.c
@@ -337,7 +337,7 @@ int sieve_compile(struct sieve_instance *svinst, const char *script_location,
 	sieve_error_args_init(&error_code_r, NULL);
 
 	if (sieve_script_create_open(svinst, script_location, script_name,
-				     &script, error_code_r) < 0) {
+				     &script, error_code_r, NULL) < 0) {
 		switch (*error_code_r) {
 		case SIEVE_ERROR_NOT_FOUND:
 			if (no_error_result) {
@@ -513,7 +513,7 @@ int sieve_open(struct sieve_instance *svinst, const char *script_location,
 
 	/* First open the scriptfile itself */
 	if (sieve_script_create_open(svinst, script_location, script_name,
-				     &script, error_code_r) < 0) {
+				     &script, error_code_r, NULL) < 0) {
 		/* Failed */
 		switch (*error_code_r) {
 		case SIEVE_ERROR_NOT_FOUND:
diff --git a/src/lib-sieve/storage/data/sieve-data-script.c b/src/lib-sieve/storage/data/sieve-data-script.c
index 45065a2d241fd92e1e9a1134bbc72ebac33341e1..6f50b29c1b0c00e6373593b35d74433c7ff8d6ed 100644
--- a/src/lib-sieve/storage/data/sieve-data-script.c
+++ b/src/lib-sieve/storage/data/sieve-data-script.c
@@ -39,7 +39,7 @@ sieve_data_script_create_from_input(struct sieve_instance *svinst,
 	int ret;
 
 	ret = sieve_storage_alloc(svinst, NULL, &sieve_data_storage,
-				  "", 0, FALSE, &storage, NULL);
+				  "", 0, FALSE, &storage, NULL, NULL);
 	i_assert(ret >= 0);
 
 	dscript = sieve_data_script_alloc();
diff --git a/src/lib-sieve/storage/file/sieve-file-script.c b/src/lib-sieve/storage/file/sieve-file-script.c
index 59b22eb0209f455e8b484e58a398a03aca21a74f..6f7f7bd73b7ffe47b81e60c958362cf51d441736 100644
--- a/src/lib-sieve/storage/file/sieve-file-script.c
+++ b/src/lib-sieve/storage/file/sieve-file-script.c
@@ -211,13 +211,13 @@ int sieve_file_script_init_from_path(struct sieve_file_storage *fstorage,
 	struct sieve_file_script *fscript;
 	struct sieve_storage *substorage;
 	enum sieve_error error_code;
+	const char *error;
 
 	*fscript_r = NULL;
 
 	if (sieve_file_storage_init_from_path(svinst, path, 0, &fsubstorage,
-					      &error_code) < 0) {
-		sieve_storage_set_error(storage, error_code,
-					"Failed to open script");
+					      &error_code, &error) < 0) {
+		sieve_storage_set_error(storage, error_code, "%s", error);
 		return -1;
 	}
 	substorage = &fsubstorage->storage;
diff --git a/src/lib-sieve/storage/file/sieve-file-storage.c b/src/lib-sieve/storage/file/sieve-file-storage.c
index 95a3d4377f030a7af3fc3bbc1e59d7dbd141d6af..160b80e28e1a1a10846394db31f1c6753fa31068 100644
--- a/src/lib-sieve/storage/file/sieve-file-storage.c
+++ b/src/lib-sieve/storage/file/sieve-file-storage.c
@@ -629,7 +629,8 @@ sieve_file_storage_autodetect(struct sieve_file_storage *fstorage,
 static int
 sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 				   const char *active_path,
-				   enum sieve_error *error_code_r)
+				   enum sieve_error *error_code_r,
+				   const char **error_r)
 {
 	struct sieve_storage *storage = &fstorage->storage;
 	const char *storage_path;
@@ -642,6 +643,8 @@ sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 		if (sieve_file_storage_stat(fstorage, storage_path) < 0) {
 			if (storage->error_code != SIEVE_ERROR_NOT_FOUND) {
 				/* Error */
+				*error_code_r = storage->error_code;
+				*error_r = storage->error;
 				return -1;
 			}
 		} else 	if (S_ISDIR(fstorage->st.st_mode)) {
@@ -656,6 +659,7 @@ sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 			"Could not find storage root directory for write access; "
 			"path was left unconfigured and autodetection failed");
 		*error_code_r = storage->error_code;
+		*error_r = storage->error;
 		return -1;
 	}
 
@@ -668,6 +672,8 @@ sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 				SIEVE_FILE_DEFAULT_PATH);
 			active_path = SIEVE_FILE_DEFAULT_PATH;
 		} else {
+			*error_code_r = storage->error_code;
+			*error_r = storage->error;
 			return -1;
 		}
 	}
@@ -679,6 +685,7 @@ sieve_file_storage_do_init_default(struct sieve_file_storage *fstorage,
 	if (sieve_file_storage_init_common(fstorage, active_path, storage_path,
 					   exists) < 0) {
 		*error_code_r = storage->error_code;
+		*error_r = storage->error;
 		return -1;
 	}
 	return 0;
@@ -688,22 +695,24 @@ int sieve_file_storage_init_default(struct sieve_instance *svinst,
 				    const char *active_path,
 				    enum sieve_storage_flags flags,
 				    struct sieve_storage **storage_r,
-				    enum sieve_error *error_code_r)
+				    enum sieve_error *error_code_r,
+				    const char **error_r)
 {
 	struct sieve_storage *storage;
 	struct sieve_file_storage *fstorage;
 	int ret;
 
 	ret = sieve_storage_alloc(svinst, NULL, &sieve_file_storage,
-				  "", flags, TRUE, &storage, error_code_r);
+				  "", flags, TRUE, &storage,
+				  error_code_r, NULL);
 	if (ret < 0)
 		return -1;
 	fstorage = container_of(storage, struct sieve_file_storage, storage);
 
 	T_BEGIN {
-		ret = sieve_file_storage_do_init_default(fstorage, active_path,
-							 error_code_r);
-	} T_END;
+		ret = sieve_file_storage_do_init_default(
+			fstorage, active_path, error_code_r, error_r);
+	}  T_END_PASS_STR_IF(ret < 0, error_r);
 	if (ret < 0) {
 		sieve_storage_unref(&storage);
 		return -1;
@@ -716,7 +725,8 @@ int sieve_file_storage_init_from_path(struct sieve_instance *svinst,
 				      const char *path,
 				      enum sieve_storage_flags flags,
 				      struct sieve_file_storage **fstorage_r,
-				      enum sieve_error *error_code_r)
+				      enum sieve_error *error_code_r,
+				      const char **error_r)
 {
 	struct sieve_storage *storage;
 	struct sieve_file_storage *fstorage;
@@ -725,10 +735,11 @@ int sieve_file_storage_init_from_path(struct sieve_instance *svinst,
 	i_assert(path != NULL);
 
 	*fstorage_r = NULL;
-	sieve_error_args_init(&error_code_r, NULL);
+	sieve_error_args_init(&error_code_r, &error_r);
 
 	ret = sieve_storage_alloc(svinst, NULL, &sieve_file_storage,
-				  "", flags, FALSE, &storage, error_code_r);
+				  "", flags, FALSE, &storage,
+				  error_code_r, error_r);
 	if (ret < 0)
 		return -1;
 	fstorage = container_of(storage, struct sieve_file_storage, storage);
@@ -739,6 +750,7 @@ int sieve_file_storage_init_from_path(struct sieve_instance *svinst,
 	} T_END;
 	if (ret < 0) {
 		*error_code_r = storage->error_code;
+		*error_r = t_strdup(storage->error);
 		sieve_storage_unref(&storage);
 		return -1;
 	}
diff --git a/src/lib-sieve/storage/file/sieve-file-storage.h b/src/lib-sieve/storage/file/sieve-file-storage.h
index eac2d98f1ddec54a0e0967432fe76726df35c6c8..405c19576e128b9f596e012eb804e7a458afe41a 100644
--- a/src/lib-sieve/storage/file/sieve-file-storage.h
+++ b/src/lib-sieve/storage/file/sieve-file-storage.h
@@ -50,7 +50,8 @@ int sieve_file_storage_init_from_path(struct sieve_instance *svinst,
 				      const char *path,
 				      enum sieve_storage_flags flags,
 				      struct sieve_file_storage **fstorage_r,
-				      enum sieve_error *error_code_r);
+				      enum sieve_error *error_code_r,
+				      const char **error_r);
 
 int sieve_file_storage_pre_modify(struct sieve_storage *storage);
 
diff --git a/src/plugins/imap-filter-sieve/imap-filter-sieve.c b/src/plugins/imap-filter-sieve/imap-filter-sieve.c
index abace63b1fe7c0366fdd81dcbfde9200b066e3c2..13b3ff9f3987b33476137c4299f1c4ca6f6d0fea 100644
--- a/src/plugins/imap-filter-sieve/imap-filter-sieve.c
+++ b/src/plugins/imap-filter-sieve/imap-filter-sieve.c
@@ -254,7 +254,8 @@ imap_filter_sieve_get_global_storage(struct imap_filter_sieve_context *sctx,
 		return -1;
 	}
 	if (sieve_storage_create(svinst, svinst->event, location, 0,
-				 &ifsuser->global_storage, &error_code) == 0) {
+				 &ifsuser->global_storage,
+				 &error_code, NULL) == 0) {
 		*storage_r = ifsuser->global_storage;
 		return 0;
 	}
diff --git a/src/plugins/imapsieve/imap-sieve.c b/src/plugins/imapsieve/imap-sieve.c
index cb7d34218e96022ee70f41bd66c2c9d6bddb15b5..7f0cfa80835d115cfeadb5bda8553505d01ab3ec 100644
--- a/src/plugins/imapsieve/imap-sieve.c
+++ b/src/plugins/imapsieve/imap-sieve.c
@@ -433,7 +433,7 @@ imap_sieve_run_init_scripts(struct imap_sieve *isieve,
 			struct sieve_script *script;
 
 			if (sieve_script_create_open(svinst, *sp, NULL, &script,
-						     &error_code) < 0) {
+						     &error_code, NULL) < 0) {
 				if (error_code == SIEVE_ERROR_TEMP_FAILURE)
 					return -1;
 				continue;
@@ -469,7 +469,7 @@ imap_sieve_run_init_scripts(struct imap_sieve *isieve,
 			struct sieve_script *script;
 
 			if (sieve_script_create_open(svinst, *sp, NULL, &script,
-						     &error_code) < 0) {
+						     &error_code, NULL) < 0) {
 				if (error_code == SIEVE_ERROR_TEMP_FAILURE)
 					return -1;
 				continue;
diff --git a/src/plugins/lda-sieve/lda-sieve-plugin.c b/src/plugins/lda-sieve/lda-sieve-plugin.c
index 2b3eda70c8d14732dc5c1544d403d185a1df8ebc..5a4ad72a21a418e2c6488296ec2f659ec1d95d9c 100644
--- a/src/plugins/lda-sieve/lda-sieve-plugin.c
+++ b/src/plugins/lda-sieve/lda-sieve-plugin.c
@@ -305,7 +305,7 @@ lda_sieve_multiscript_get_scripts(struct sieve_instance *svinst,
 	int ret;
 
 	ret = sieve_script_sequence_create(svinst, location,
-					   &sseq, error_code_r);
+					   &sseq, error_code_r, NULL);
 	if (ret < 0) {
 		if (*error_code_r == SIEVE_ERROR_NOT_FOUND) {
 			*error_code_r = SIEVE_ERROR_NONE;
@@ -317,7 +317,7 @@ lda_sieve_multiscript_get_scripts(struct sieve_instance *svinst,
 	}
 
 	while ((ret = sieve_script_sequence_next(sseq, &script,
-						 error_code_r)) > 0)
+						 error_code_r, NULL)) > 0)
 		array_append(scripts, &script, 1);
 
 	sieve_script_sequence_free(&sseq);
@@ -857,7 +857,7 @@ static int lda_sieve_find_scripts(struct lda_sieve_run_context *srctx)
 	if (sieve_discard != NULL && *sieve_discard != '\0') {
 		if (sieve_script_create_open(svinst, sieve_discard, NULL,
 					     &srctx->discard_script,
-					     &error_code) < 0) {
+					     &error_code, NULL) < 0) {
 			switch (error_code) {
 			case SIEVE_ERROR_NOT_FOUND:
 				e_debug(sieve_get_event(svinst),