Index: src/wp-admin/includes/ajax-actions.php
===================================================================
--- src/wp-admin/includes/ajax-actions.php	(revision 40958)
+++ src/wp-admin/includes/ajax-actions.php	(working copy)
@@ -1100,6 +1100,11 @@
 	}
 
 	$comment_id = wp_new_comment( $commentdata );
+
+	if ( is_wp_error( $comment_id ) ) {
+		wp_die ( $comment_id->get_error_message() );
+	}
+
 	$comment = get_comment($comment_id);
 	if ( ! $comment ) wp_die( 1 );
 
Index: tests/phpunit/tests/ajax/ReplytoComment.php
===================================================================
--- tests/phpunit/tests/ajax/ReplytoComment.php	(revision 40958)
+++ tests/phpunit/tests/ajax/ReplytoComment.php	(working copy)
@@ -222,4 +222,34 @@
 		}
 		return $sql;
 	}
+
+	/**
+	 * @ticket 39730
+	 */
+	public function test_pre_comments_approved () {
+
+		// Become an administrator
+		$this->_setRole( 'administrator' );
+
+		// Set up a default request
+		$_POST['_ajax_nonce-replyto-comment'] = wp_create_nonce( 'replyto-comment' );
+		$_POST['content']                     = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.';
+		$_POST['comment_post_ID']             = self::$comment_post->ID;
+
+		// Simulate filter check error
+		add_filter( 'pre_comment_approved', array( $this, '_pre_comment_approved_filter' ), 10, 2 );
+
+		// Make the request
+		$this->setExpectedException( 'WPAjaxDieStopException', 'pre_comment_approved filter fails for new comment' );
+		$this->_handleAjax( 'replyto-comment' );
+
+		remove_filter( 'pre_comment_approved', array( $this, '_pre_comment_approved_filter' ), 10, 2 );
+	}
+
+	/**
+	 *  Block comments from being saved 'pre_comment_approved', by returning WP_Error
+	 */
+	function _pre_comment_approved_filter ( $approved, $commentdata ) {
+		return new WP_Error( 'comment_wrong', __( 'pre_comment_approved filter fails for new comment' ), 403 );
+	}
 }
Index: src/wp-trackback.php
===================================================================
--- src/wp-trackback.php	(revision 40958)
+++ src/wp-trackback.php	(working copy)
@@ -126,7 +126,12 @@
 
 	$commentdata = compact('comment_post_ID', 'comment_author', 'comment_author_email', 'comment_author_url', 'comment_content', 'comment_type');
 
-	wp_new_comment($commentdata);
+	$result = wp_new_comment($commentdata);
+
+	if ( is_wp_error( $result ) ) {
+		trackback_response( 1, $result->get_error_message() );
+	}
+
 	$trackback_id = $wpdb->insert_id;
 
 	/**
Index: src/wp-includes/class-wp-xmlrpc-server.php
===================================================================
--- src/wp-includes/class-wp-xmlrpc-server.php	(revision 40958)
+++ src/wp-includes/class-wp-xmlrpc-server.php	(working copy)
@@ -6505,6 +6505,10 @@
 
 		$comment_ID = wp_new_comment($commentdata);
 
+		if ( is_wp_error( $comment_ID ) ) {
+			return $this->pingback_error( 0, $comment_ID->get_error_message() );
+		}
+
 		/**
 		 * Fires after a post pingback has been sent.
 		 *
Index: src/wp-includes/comment.php
===================================================================
--- src/wp-includes/comment.php	(revision 40958)
+++ src/wp-includes/comment.php	(working copy)
@@ -756,10 +756,13 @@
 	/**
 	 * Filters a comment's approval status before it is set.
 	 *
+	 * Returning a WP_Error value from the filter will shortcircuit comment insertion and
+	 * allow skipping further processing.
+	 * 
 	 * @since 2.1.0
 	 *
-	 * @param bool|string $approved    The approval status. Accepts 1, 0, or 'spam'.
-	 * @param array       $commentdata Comment data.
+	 * @param bool|string|WP_Error $approved    The approval status. Accepts 1, 0, 'spam' or WP_Error.
+	 * @param array                $commentdata Comment data.
 	 */
 	$approved = apply_filters( 'pre_comment_approved', $approved, $commentdata );
 	return $approved;
