diff --git a/src/lib-sieve/util/program-client-local.c b/src/lib-sieve/util/program-client-local.c
index 35e9f9730de3a42875206a229a5fce8e58b47b8f..0e17b04e5880c7331193359b5520857ff2752c2c 100644
--- a/src/lib-sieve/util/program-client-local.c
+++ b/src/lib-sieve/util/program-client-local.c
@@ -426,19 +426,6 @@ static int program_client_local_disconnect
 	return -1;
 }
 
-static void program_client_local_failure
-(struct program_client *pclient, enum program_client_error error)
-{
-	switch ( error ) {
-	case PROGRAM_CLIENT_ERROR_RUN_TIMEOUT:
-		i_error("program `%s' execution timed out (> %d secs)",
-			pclient->path, pclient->set.input_idle_timeout_secs);
-		break;
-	default:
-		break;
-	}
-}
-
 struct program_client *program_client_local_create
 (const char *bin_path, const char *const *args,
 	const struct program_client_settings *set)
@@ -452,7 +439,6 @@ struct program_client *program_client_local_create
 	pclient->client.connect = program_client_local_connect;
 	pclient->client.close_output = program_client_local_close_output;
 	pclient->client.disconnect = program_client_local_disconnect;
-	pclient->client.failure = program_client_local_failure;
 	pclient->pid = -1;
 
 	return &pclient->client;
diff --git a/src/lib-sieve/util/program-client-private.h b/src/lib-sieve/util/program-client-private.h
index 8ee4666919efba9d88cf60556246a7c7c71b4489..9432f24d3c151ce9c204057328b99e650efbd3c4 100644
--- a/src/lib-sieve/util/program-client-private.h
+++ b/src/lib-sieve/util/program-client-private.h
@@ -11,7 +11,7 @@ enum program_client_error {
 	PROGRAM_CLIENT_ERROR_CONNECT_TIMEOUT,
 	PROGRAM_CLIENT_ERROR_RUN_TIMEOUT,
 	PROGRAM_CLIENT_ERROR_IO,
-	PROGRAM_CLIENT_ERROR_UNKNOWN
+	PROGRAM_CLIENT_ERROR_OTHER
 };
 
 struct program_client_extra_fd {
@@ -51,8 +51,6 @@ struct program_client {
 	int (*connect)(struct program_client *pclient);
 	int (*close_output)(struct program_client *pclient);
 	int (*disconnect)(struct program_client *pclient, bool force);
-	void (*failure)
-		(struct program_client *pclient, enum program_client_error error);
 	
 	unsigned int debug:1;
 	unsigned int disconnected:1;
diff --git a/src/lib-sieve/util/program-client-remote.c b/src/lib-sieve/util/program-client-remote.c
index d484389a5d547764b071a19284ca92a2acb6d1bb..b50436fc85b5c94be0ee4cc7bf689d7766652bde 100644
--- a/src/lib-sieve/util/program-client-remote.c
+++ b/src/lib-sieve/util/program-client-remote.c
@@ -205,6 +205,9 @@ static void program_client_remote_connected(struct program_client *pclient)
 
 	if ( o_stream_send
 		(pclient->program_output, str_data(str), str_len(str)) < 0 ) {
+		i_error("write(%s) failed: %s",
+			o_stream_get_name(pclient->program_output),
+			o_stream_get_error(pclient->program_output));
 		program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
 		return;
 	}
@@ -294,23 +297,6 @@ static int program_client_remote_disconnect
 	return ret;
 }
 
-static void program_client_remote_failure
-(struct program_client *pclient, enum program_client_error error)
-{
-	switch ( error ) {
-	case PROGRAM_CLIENT_ERROR_CONNECT_TIMEOUT:
-		i_error("program `%s' socket connection timed out (> %d msecs)",
-			pclient->path, pclient->set.client_connect_timeout_msecs);
-		break;
-	case PROGRAM_CLIENT_ERROR_RUN_TIMEOUT:
-		i_error("program `%s' execution timed out (> %d secs)",
-			pclient->path, pclient->set.input_idle_timeout_secs);
-		break;
-	default:
-		break;
-	}
-}
-
 struct program_client *program_client_remote_create
 (const char *socket_path, const char *const *args, 
 	const struct program_client_settings *set, bool noreply)
@@ -324,7 +310,6 @@ struct program_client *program_client_remote_create
 	pclient->client.connect = program_client_remote_connect;
 	pclient->client.close_output = program_client_remote_close_output;
 	pclient->client.disconnect = program_client_remote_disconnect;
-	pclient->client.failure = program_client_remote_failure;
 	pclient->noreply = noreply;
 
 	return &pclient->client;
diff --git a/src/lib-sieve/util/program-client.c b/src/lib-sieve/util/program-client.c
index 1b9b2621818ee15ab4abf3d4963ab39d262682d0..bf0ca3ce0c5ebcfef9f293735f6727f9e5152b4a 100644
--- a/src/lib-sieve/util/program-client.c
+++ b/src/lib-sieve/util/program-client.c
@@ -19,11 +19,15 @@
 
 static void program_client_timeout(struct program_client *pclient)
 {
+	i_error("program `%s' execution timed out (> %d secs)",
+		pclient->path, pclient->set.input_idle_timeout_secs);
 	program_client_fail(pclient, PROGRAM_CLIENT_ERROR_RUN_TIMEOUT);
 }
 
 static void program_client_connect_timeout(struct program_client *pclient)
 {
+	i_error("program `%s' socket connection timed out (> %d msecs)",
+		pclient->path, pclient->set.client_connect_timeout_msecs);
 	program_client_fail(pclient, PROGRAM_CLIENT_ERROR_CONNECT_TIMEOUT);
 }
 
@@ -118,7 +122,7 @@ static void program_client_disconnect
 	
 	pclient->disconnected = TRUE;
 	if (error && pclient->error == PROGRAM_CLIENT_ERROR_NONE ) {
-		pclient->error = PROGRAM_CLIENT_ERROR_UNKNOWN;
+		pclient->error = PROGRAM_CLIENT_ERROR_OTHER;
 	}
 }
 
@@ -130,8 +134,6 @@ void program_client_fail
 
 	pclient->error = error;
 	program_client_disconnect(pclient, TRUE);
-
-	pclient->failure(pclient, error);
 }
 
 static bool program_client_input_pending(struct program_client *pclient)
@@ -168,8 +170,12 @@ static int program_client_program_output(struct program_client *pclient)
 	int ret = 0;
 
 	if ((ret = o_stream_flush(output)) <= 0) {
-		if (ret < 0)
+		if (ret < 0) {
+			i_error("write(%s) failed: %s",
+				o_stream_get_name(output),
+				o_stream_get_error(output));
 			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
+		}
 		return ret;
 	}
 
@@ -179,6 +185,9 @@ static int program_client_program_output(struct program_client *pclient)
 				ssize_t sent;
 	
 				if ( (sent=o_stream_send(output, data, size)) < 0 ) {
+					i_error("write(%s) failed: %s",
+						o_stream_get_name(output),
+						o_stream_get_error(output));
 					program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
 					return -1;
 				}
@@ -193,7 +202,10 @@ static int program_client_program_output(struct program_client *pclient)
 			return 1;
 
 		if ( ret < 0 ) {
-			if ( !input->eof ) {
+			if ( input->stream_errno != 0 ) {
+				i_error("read(%s) failed: %s",
+					i_stream_get_name(input),
+					i_stream_get_error(input));
 				program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
 				return -1;
 			} else if ( !i_stream_have_bytes_left(input) ) {
@@ -201,8 +213,12 @@ static int program_client_program_output(struct program_client *pclient)
 				input = NULL;
 
 				if ( (ret = o_stream_flush(output)) <= 0 ) {
-					if ( ret < 0 )
+					if ( ret < 0 ) {
+						i_error("write(%s) failed: %s",
+							o_stream_get_name(output),
+							o_stream_get_error(output));
 						program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
+					}
 					return ret;
 				}
 			} 
@@ -213,7 +229,7 @@ static int program_client_program_output(struct program_client *pclient)
 		if ( !program_client_input_pending(pclient) ) {
 			program_client_disconnect(pclient, FALSE);
 		} else if (program_client_close_output(pclient) < 0) {
-			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
+			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_OTHER);
 		}
 	}
 	return 1;
@@ -233,6 +249,9 @@ static void program_client_program_input(struct program_client *pclient)
 				ssize_t sent;
 
 				if ( (sent=o_stream_send(output, data, size)) < 0 ) {
+					i_error("write(%s) failed: %s",
+						o_stream_get_name(output),
+						o_stream_get_error(output));
 					program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
 					return;
 				}
@@ -243,12 +262,15 @@ static void program_client_program_input(struct program_client *pclient)
 		}
 
 		if ( ret < 0 ) {
-			if ( i_stream_is_eof(input) ) {
+			if ( input->stream_errno != 0 ) {
+				i_error("read(%s) failed: %s",
+					i_stream_get_name(input),
+					i_stream_get_error(input));
+				program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
+			} else {
 				if ( !program_client_input_pending(pclient) )
 					program_client_disconnect(pclient, FALSE);
-				return;
 			}
-			program_client_fail(pclient, PROGRAM_CLIENT_ERROR_IO);
 		}
 	}
 }
@@ -424,6 +446,7 @@ void program_client_init_streams(struct program_client *pclient)
 	if ( pclient->fd_out >= 0 ) {
 		pclient->program_output =
 			o_stream_create_fd(pclient->fd_out, MAX_OUTPUT_BUFFER_SIZE, FALSE);
+		o_stream_set_name(pclient->program_output, "program stdin");
 	}
 	if ( pclient->fd_in >= 0 ) {
 		struct istream *input;
@@ -442,6 +465,8 @@ void program_client_init_streams(struct program_client *pclient)
 		}
 
 		pclient->program_input = input;
+		i_stream_set_name(pclient->program_input, "program stdout");
+
 		pclient->io = io_add
 			(pclient->fd_in, IO_READ, program_client_program_input, pclient);
 	}
@@ -456,6 +481,8 @@ void program_client_init_streams(struct program_client *pclient)
 			i_assert( efds[i].parent_fd >= 0 );
 			efds[i].input = i_stream_create_fd
 				(efds[i].parent_fd, (size_t)-1, FALSE);
+			i_stream_set_name(efds[i].input,
+				t_strdup_printf("program output fd=%d", efds[i].child_fd));
 			efds[i].io = io_add
 				(efds[i].parent_fd, IO_READ, program_client_extra_fd_input, &efds[i]);
 		}
@@ -504,6 +531,9 @@ int program_client_run(struct program_client *pclient)
 
 		/* run i/o event loop */
 		if ( ret < 0 ) {
+			i_error("write(%s) failed: %s",
+				o_stream_get_name(pclient->program_output),
+				o_stream_get_error(pclient->program_output));
 			pclient->error = PROGRAM_CLIENT_ERROR_IO;
 		} else if ( !pclient->disconnected &&
 			(ret == 0 || program_client_input_pending(pclient)) ) {