diff --git a/src/knot/server/tcp-handler.c b/src/knot/server/tcp-handler.c
index 1f18abfdf8ab5ad1220b4d56a47533d928f5fe8d..5b6ac941f0ed7e27eddb76fd0fd2d2d0ce94d286 100644
--- a/src/knot/server/tcp-handler.c
+++ b/src/knot/server/tcp-handler.c
@@ -543,7 +543,16 @@ int tcp_loop_master(dthread_t *thread)
 		}
 
 		for (unsigned i = 0; nfds > 0 && i < set.n; ++i) {
-			/* Skip inactive. */
+
+			/* Error events. */
+			if (set.pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
+				socket_close(set.pfd[i].fd);
+				fdset_remove(&set, i);
+				--nfds;   /* Treat error event as activity. */
+				continue; /* Stay on the same index. */
+			}
+
+			/* Accept POLLIN events. */
 			if (!(set.pfd[i].revents & POLLIN))
 				continue;
 
@@ -611,6 +620,15 @@ int tcp_loop_worker(dthread_t *thread)
 		unsigned i = 0;
 		while (nfds > 0 && i < set->n) {
 
+			/* Terminate faulty connections. */
+			int fd = set->pfd[i].fd;
+			if (set->pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
+				fdset_remove(set, i);
+				close(fd);
+				--nfds;   /* Treat error event as activity. */
+				continue; /* Stay on the same index. */
+			}
+
 			if (!(set->pfd[i].revents & set->pfd[i].events)) {
 				/* Skip inactive. */
 				++i;
@@ -621,7 +639,6 @@ int tcp_loop_worker(dthread_t *thread)
 			}
 
 			/* Register new TCP client or process a query. */
-			int fd = set->pfd[i].fd;
 			if (fd == w->pipe[0]) {
 				tcp_loop_assign(fd, set);
 			} else {
diff --git a/src/knot/server/xfr-handler.c b/src/knot/server/xfr-handler.c
index 90b0a42ecab65c8dc9632aebc454aa290f011ef0..a99b5d342914ab93305d40969fccc8ddeda01580 100644
--- a/src/knot/server/xfr-handler.c
+++ b/src/knot/server/xfr-handler.c
@@ -1101,21 +1101,19 @@ int xfr_worker(dthread_t *thread)
 		unsigned i = 0;
 		while (nfds > 0 && i < set.n && !dt_is_cancelled(thread)) {
 
-			if (!(set.pfd[i].revents & set.pfd[i].events)) {
-				/* Skip inactive. */
-				++i;
-				continue;
-			} else {
+			knot_ns_xfr_t *rq = (knot_ns_xfr_t *)set.ctx[i];
+			if (set.pfd[i].revents & (POLLERR|POLLHUP|POLLNVAL)) {
+				/* Error events. */
+				--nfds;           /* Treat error event as activity. */
+				ret = KNOT_ECONN; /* Force disconnect */
+			} else if (set.pfd[i].revents & set.pfd[i].events) {
 				/* One less active event. */
 				--nfds;
-			}
-
-			/* Process pending tasks. */
-			knot_ns_xfr_t *rq = (knot_ns_xfr_t *)set.ctx[i];
-			if (rq->flags & XFR_FLAG_CONNECTING) {
-				ret = xfr_async_finish(&set, i);
-			} else {
-				ret = xfr_process_event(w, rq);
+				/* Process pending tasks. */
+				if (rq->flags & XFR_FLAG_CONNECTING)
+					ret = xfr_async_finish(&set, i);
+				else
+					ret = xfr_process_event(w, rq);
 			}
 
 			/* Check task state. */