diff --git a/src/backend/libpq/auth-scram.c b/src/backend/libpq/auth-scram.c
index 99feb0ce94..366a11feb8 100644
--- a/src/backend/libpq/auth-scram.c
+++ b/src/backend/libpq/auth-scram.c
@@ -283,11 +283,13 @@ pg_be_scram_exchange(void *opaq, char *input, int inputlen,
 	if (inputlen == 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 (errmsg("malformed SCRAM message (empty message)"))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("The message is empty.")));
 	if (inputlen != strlen(input))
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 (errmsg("malformed SCRAM message (length mismatch)"))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Input length does not match.")));
 
 	switch (state->state)
 	{
@@ -319,7 +321,8 @@ pg_be_scram_exchange(void *opaq, char *input, int inputlen,
 			if (!verify_final_nonce(state))
 				ereport(ERROR,
 						(errcode(ERRCODE_PROTOCOL_VIOLATION),
-					   (errmsg("invalid SCRAM response (nonce mismatch)"))));
+						 errmsg("invalid SCRAM response"),
+						 errdetail("Nonce does not match.")));
 
 			/*
 			 * Now check the final nonce and the client proof.
@@ -582,14 +585,16 @@ read_attr_value(char **input, char attr)
 	if (*begin != attr)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-		(errmsg("malformed SCRAM message (attribute '%c' expected, %s found)",
-				attr, sanitize_char(*begin)))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Expected attribute '%c' but found %s.",
+						   attr, sanitize_char(*begin))));
 	begin++;
 
 	if (*begin != '=')
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-		 (errmsg("malformed SCRAM message (expected = in attr %c)", attr))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Expected character = for attribute %c.", attr)));
 	begin++;
 
 	end = begin;
@@ -669,8 +674,9 @@ read_any_attr(char **input, char *attr_p)
 		  (attr >= 'a' && attr <= 'z')))
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 (errmsg("malformed SCRAM message (attribute expected, invalid char %s found)",
-						 sanitize_char(attr)))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Attribute expected, but found invalid character %s.",
+						   sanitize_char(attr))));
 	if (attr_p)
 		*attr_p = attr;
 	begin++;
@@ -678,7 +684,8 @@ read_any_attr(char **input, char *attr_p)
 	if (*begin != '=')
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-		 (errmsg("malformed SCRAM message (expected = in attr %c)", attr))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Expected character = for attribute %c.", attr)));
 	begin++;
 
 	end = begin;
@@ -795,14 +802,16 @@ read_client_first_message(scram_state *state, char *input)
 		default:
 			ereport(ERROR,
 					(errcode(ERRCODE_PROTOCOL_VIOLATION),
-					 (errmsg("malformed SCRAM message (unexpected channel-binding flag %s)",
-							 sanitize_char(*input)))));
+					 errmsg("malformed SCRAM message"),
+					 errdetail("Unexpected channel-binding flag %s.",
+							   sanitize_char(*input))));
 	}
 	if (*input != ',')
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 errmsg("malformed SCRAM message (comma expected, got %s)",
-						sanitize_char(*input))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Comma expected, but found character %s.",
+						   sanitize_char(*input))));
 	input++;
 
 	/*
@@ -815,8 +824,9 @@ read_client_first_message(scram_state *state, char *input)
 	if (*input != ',')
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 errmsg("malformed SCRAM message (unexpected attribute %s in client-first-message)",
-						sanitize_char(*input))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Unexpected attribute %s in client-first-message.",
+						   sanitize_char(*input))));
 	input++;
 
 	state->client_first_message_bare = pstrdup(input);
@@ -1044,14 +1054,16 @@ read_client_final_message(scram_state *state, char *input)
 	if (pg_b64_decode(value, strlen(value), client_proof) != SCRAM_KEY_LEN)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 (errmsg("malformed SCRAM message (malformed proof in client-final-message"))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Malformed proof in client-final-message.")));
 	memcpy(state->ClientProof, client_proof, SCRAM_KEY_LEN);
 	pfree(client_proof);
 
 	if (*p != '\0')
 		ereport(ERROR,
 				(errcode(ERRCODE_PROTOCOL_VIOLATION),
-				 (errmsg("malformed SCRAM message (garbage at end of client-final-message)"))));
+				 errmsg("malformed SCRAM message"),
+				 errdetail("Garbage found at the end of client-final-message.")));
 
 	state->client_final_message_without_proof = palloc(proof - begin + 1);
 	memcpy(state->client_final_message_without_proof, input, proof - begin);
