diff --git a/CHANGES b/CHANGES
index b6394125a13dd2b49e25f2fbd311e509a5d8379c..9f00d61ca9420eb4189b2edee0895cad80368573 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,7 @@ OpenLDAP 2.4.14 Engineering
 	Fixed libldap_r deref building (ITS#5768)
 	Fixed slapd syncrepl rename handling (ITS#5809)
 	Fixed slapd syncrepl MMR when adding new server (ITS#5850)
+	Fixed slapd-meta double response sending (ITS#5854)
 	Build Environment
 		Fixed test049,test050 to work on windows (ITS#5842)
 
diff --git a/servers/slapd/back-ldap/back-ldap.h b/servers/slapd/back-ldap/back-ldap.h
index a5242e0a88ebf40615cacd6a210d44c9928b03e3..59bd2921a90bcae10f433e74d8f3d5b43221ad55 100644
--- a/servers/slapd/back-ldap/back-ldap.h
+++ b/servers/slapd/back-ldap/back-ldap.h
@@ -393,6 +393,8 @@ typedef struct ldapinfo_t {
 	time_t			li_timeout[ SLAP_OP_LAST ];
 } ldapinfo_t;
 
+#define	LDAP_ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)
+
 typedef enum ldap_back_send_t {
 	LDAP_BACK_DONTSEND		= 0x00,
 	LDAP_BACK_SENDOK		= 0x01,
diff --git a/servers/slapd/back-ldap/bind.c b/servers/slapd/back-ldap/bind.c
index aa2d87983cef14f9786a8ef86e1e07d8fe553f8b..c7771b006252c2a0545be0feeeb10d902074fae6 100644
--- a/servers/slapd/back-ldap/bind.c
+++ b/servers/slapd/back-ldap/bind.c
@@ -1637,8 +1637,6 @@ ldap_back_op_result(
 	char		**refs = NULL;
 	LDAPControl	**ctrls = NULL;
 
-#define	ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)
-
 	rs->sr_text = NULL;
 	rs->sr_matched = NULL;
 	rs->sr_ref = NULL;
@@ -1647,7 +1645,7 @@ ldap_back_op_result(
 	/* if the error recorded in the reply corresponds
 	 * to a successful state, get the error from the
 	 * remote server response */
-	if ( ERR_OK( rs->sr_err ) ) {
+	if ( LDAP_ERR_OK( rs->sr_err ) ) {
 		int		rc;
 		struct timeval	tv;
 		LDAPMessage	*res = NULL;
@@ -1800,7 +1798,7 @@ retry:;
 	/* if the error in the reply structure is not
 	 * LDAP_SUCCESS, try to map it from client 
 	 * to server error */
-	if ( !ERR_OK( rs->sr_err ) ) {
+	if ( !LDAP_ERR_OK( rs->sr_err ) ) {
 		rs->sr_err = slap_map_api2result( rs );
 
 		/* internal ops ( op->o_conn == NULL ) 
@@ -1825,8 +1823,8 @@ retry:;
 		}
 
 	} else if ( op->o_conn &&
-		( ( ( sendok & LDAP_BACK_SENDOK ) && ERR_OK( rs->sr_err ) )
-			|| ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )
+		( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) )
+			|| ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) )
 	{
 		send_ldap_result( op, rs );
 	}
@@ -1859,7 +1857,7 @@ retry:;
 		rs->sr_ctrls = NULL;
 	}
 
-	return( ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
+	return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
 }
 
 /* return true if bound, false if failed */
diff --git a/servers/slapd/back-meta/add.c b/servers/slapd/back-meta/add.c
index bbe9f6a1eb7711d0e1cba99957c348447beb495b..7eb3848ca546d41f52f773a633ef24b8f6dce1b0 100644
--- a/servers/slapd/back-meta/add.c
+++ b/servers/slapd/back-meta/add.c
@@ -45,7 +45,7 @@ meta_back_add( Operation *op, SlapReply *rs )
 	struct berval	mdn = BER_BVNULL, mapped;
 	dncookie	dc;
 	int		msgid;
-	int		do_retry = 1;
+	ldap_back_send_t	retrying = LDAP_BACK_RETRYING;
 	LDAPControl	**ctrls = NULL;
 
 	Debug(LDAP_DEBUG_ARGS, "==> meta_back_add: %s\n",
@@ -178,9 +178,9 @@ retry:;
 	rs->sr_err = ldap_add_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
 			      attrs, ctrls, NULL, &msgid );
 	rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-		mt->mt_timeout[ SLAP_OP_ADD ], LDAP_BACK_SENDRESULT );
-	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-		do_retry = 0;
+		mt->mt_timeout[ SLAP_OP_ADD ], ( LDAP_BACK_SENDRESULT | retrying ) );
+	if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+		retrying &= ~LDAP_BACK_RETRYING;
 		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
 			/* if the identity changed, there might be need to re-authz */
 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c
index 439f05dd8176e16aae9a3394d1408ee943d88f3c..2f989fbd3ebae5a47320521ddffc5c7a78f7cb2d 100644
--- a/servers/slapd/back-meta/bind.c
+++ b/servers/slapd/back-meta/bind.c
@@ -953,9 +953,7 @@ meta_back_op_result(
 		metatarget_t		*mt = mi->mi_targets[ candidate ];
 		metasingleconn_t	*msc = &mc->mc_conns[ candidate ];
 
-#define	ERR_OK(err) ((err) == LDAP_SUCCESS || (err) == LDAP_COMPARE_FALSE || (err) == LDAP_COMPARE_TRUE)
-
-		if ( ERR_OK( rs->sr_err ) ) {
+		if ( LDAP_ERR_OK( rs->sr_err ) ) {
 			int		rc;
 			struct timeval	tv;
 			LDAPMessage	*res = NULL;
@@ -1087,7 +1085,7 @@ retry:;
 		/* if the error in the reply structure is not
 		 * LDAP_SUCCESS, try to map it from client 
 		 * to server error */
-		if ( !ERR_OK( rs->sr_err ) ) {
+		if ( !LDAP_ERR_OK( rs->sr_err ) ) {
 			rs->sr_err = slap_map_api2result( rs );
 
 			/* internal ops ( op->o_conn == NULL ) 
@@ -1206,9 +1204,17 @@ retry:;
 		rs->sr_matched = matched;
 	}
 
-	if ( op->o_conn &&
-		( ( sendok & LDAP_BACK_SENDOK ) 
-			|| ( ( sendok & LDAP_BACK_SENDERR ) && rs->sr_err != LDAP_SUCCESS ) ) )
+	if ( rs->sr_err == LDAP_UNAVAILABLE ) {
+		if ( !( sendok & LDAP_BACK_RETRYING ) ) {
+			if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
+				if ( rs->sr_text == NULL ) rs->sr_text = "Proxy operation retry failed";
+				send_ldap_result( op, rs );
+			}
+		}
+
+	} else if ( op->o_conn &&
+		( ( ( sendok & LDAP_BACK_SENDOK ) && LDAP_ERR_OK( rs->sr_err ) )
+			|| ( ( sendok & LDAP_BACK_SENDERR ) && !LDAP_ERR_OK( rs->sr_err ) ) ) )
 	{
 		send_ldap_result( op, rs );
 	}
@@ -1235,7 +1241,7 @@ retry:;
 	rs->sr_ref = save_ref;
 	rs->sr_ctrls = save_ctrls;
 
-	return( ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
+	return( LDAP_ERR_OK( rs->sr_err ) ? LDAP_SUCCESS : rs->sr_err );
 }
 
 /*
diff --git a/servers/slapd/back-meta/compare.c b/servers/slapd/back-meta/compare.c
index 5fbb9fa92875449073c0d19f92bb765d55960a7e..0651bbcb602a4e192073c29f05371a40de299194 100644
--- a/servers/slapd/back-meta/compare.c
+++ b/servers/slapd/back-meta/compare.c
@@ -44,7 +44,7 @@ meta_back_compare( Operation *op, SlapReply *rs )
 	struct berval	mapped_attr = op->orc_ava->aa_desc->ad_cname;
 	struct berval	mapped_value = op->orc_ava->aa_value;
 	int		msgid;
-	int		do_retry = 1;
+	ldap_back_send_t	retrying = LDAP_BACK_RETRYING;
 	LDAPControl	**ctrls = NULL;
 
 	mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
@@ -124,9 +124,9 @@ retry:;
 			ctrls, NULL, &msgid );
 
 	rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-		mt->mt_timeout[ SLAP_OP_COMPARE ], LDAP_BACK_SENDRESULT );
-	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-		do_retry = 0;
+		mt->mt_timeout[ SLAP_OP_COMPARE ], ( LDAP_BACK_SENDRESULT | retrying ) );
+	if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+		retrying &= ~LDAP_BACK_RETRYING;
 		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
 			/* if the identity changed, there might be need to re-authz */
 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
diff --git a/servers/slapd/back-meta/delete.c b/servers/slapd/back-meta/delete.c
index b3335a09c8aab0e05acf847fb2fa14cc4942452f..8ae77037f0c5ac5b5f6461d51fa39fcbf2e20a6f 100644
--- a/servers/slapd/back-meta/delete.c
+++ b/servers/slapd/back-meta/delete.c
@@ -41,7 +41,7 @@ meta_back_delete( Operation *op, SlapReply *rs )
 	struct berval	mdn = BER_BVNULL;
 	dncookie	dc;
 	int		msgid;
-	int		do_retry = 1;
+	ldap_back_send_t	retrying = LDAP_BACK_RETRYING;
 	LDAPControl	**ctrls = NULL;
 
 	mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
@@ -76,9 +76,9 @@ retry:;
 	rs->sr_err = ldap_delete_ext( mc->mc_conns[ candidate ].msc_ld,
 			mdn.bv_val, ctrls, NULL, &msgid );
 	rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-		mt->mt_timeout[ SLAP_OP_DELETE ], LDAP_BACK_SENDRESULT );
-	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-		do_retry = 0;
+		mt->mt_timeout[ SLAP_OP_DELETE ], ( LDAP_BACK_SENDRESULT | retrying ) );
+	if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+		retrying &= ~LDAP_BACK_RETRYING;
 		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
 			/* if the identity changed, there might be need to re-authz */
 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
diff --git a/servers/slapd/back-meta/modify.c b/servers/slapd/back-meta/modify.c
index e2c735b9f1b61b30bef0880e682e4d2e1dfab83c..e8e6dd77f38ee0ec7d43d96c1683313b2238f10a 100644
--- a/servers/slapd/back-meta/modify.c
+++ b/servers/slapd/back-meta/modify.c
@@ -47,7 +47,7 @@ meta_back_modify( Operation *op, SlapReply *rs )
 	struct berval	mapped;
 	dncookie	dc;
 	int		msgid;
-	int		do_retry = 1;
+	ldap_back_send_t	retrying = LDAP_BACK_RETRYING;
 	LDAPControl	**ctrls = NULL;
 
 	mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
@@ -187,9 +187,9 @@ retry:;
 	rs->sr_err = ldap_modify_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
 			modv, ctrls, NULL, &msgid );
 	rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-		mt->mt_timeout[ SLAP_OP_MODIFY ], LDAP_BACK_SENDRESULT );
-	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-		do_retry = 0;
+		mt->mt_timeout[ SLAP_OP_MODIFY ], ( LDAP_BACK_SENDRESULT | retrying ) );
+	if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+		retrying &= ~LDAP_BACK_RETRYING;
 		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
 			/* if the identity changed, there might be need to re-authz */
 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );
diff --git a/servers/slapd/back-meta/modrdn.c b/servers/slapd/back-meta/modrdn.c
index 90f708e9d645e34128feac7525a7697130ec0c07..7d9f290189421ec8c37ed4c5796dcb860f67e86b 100644
--- a/servers/slapd/back-meta/modrdn.c
+++ b/servers/slapd/back-meta/modrdn.c
@@ -42,7 +42,7 @@ meta_back_modrdn( Operation *op, SlapReply *rs )
 			mnewSuperior = BER_BVNULL;
 	dncookie	dc;
 	int		msgid;
-	int		do_retry = 1;
+	ldap_back_send_t	retrying = LDAP_BACK_RETRYING;
 	LDAPControl	**ctrls = NULL;
 	struct berval	newrdn = BER_BVNULL;
 
@@ -139,9 +139,9 @@ retry:;
 			mnewSuperior.bv_val, op->orr_deleteoldrdn,
 			ctrls, NULL, &msgid );
 	rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
-		mt->mt_timeout[ SLAP_OP_MODRDN ], LDAP_BACK_SENDRESULT );
-	if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
-		do_retry = 0;
+		mt->mt_timeout[ SLAP_OP_MODRDN ], ( LDAP_BACK_SENDRESULT | retrying ) );
+	if ( rs->sr_err == LDAP_UNAVAILABLE && retrying ) {
+		retrying &= ~LDAP_BACK_RETRYING;
 		if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
 			/* if the identity changed, there might be need to re-authz */
 			(void)mi->mi_ldap_extra->controls_free( op, rs, &ctrls );