diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index c76fdf59ec..2f208abcc1 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -807,7 +807,7 @@ ExecCheckXactReadOnly(PlannedStmt *plannedstmt)
 		if (isTempNamespace(get_rel_namespace(perminfo->relid)))
 			continue;
 
-		PreventCommandIfReadOnly(CreateCommandName((Node *) plannedstmt));
+		PreventCommandIfReadOnly(plannedstmt->hasModifyingCTE ? NULL : CreateCommandName((Node *) plannedstmt));
 	}
 
 	if (plannedstmt->commandType != CMD_SELECT || plannedstmt->hasModifyingCTE)
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index f55424eb5a..5377e5994c 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -522,9 +522,11 @@ init_execution_state(List *queryTree_list,
 			if (fcache->readonly_func && !CommandIsReadOnly(stmt))
 				ereport(ERROR,
 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 CreateCommandTag((Node *) stmt) == CMDTAG_SELECT ?
+						 errmsg("A WITH clause containing a data-modifying statement is not allowed in a non-volatile function")
 				/* translator: %s is a SQL statement name */
-						 errmsg("%s is not allowed in a non-volatile function",
-								CreateCommandName((Node *) stmt))));
+						 : errmsg("%s is not allowed in a non-volatile function",
+								  CreateCommandName((Node *) stmt))));
 
 			/* OK, build the execution_state for this query */
 			newes = (execution_state *) palloc(sizeof(execution_state));
diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 33975687b3..a57d3364c8 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -1738,9 +1738,11 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan,
 			if (!CommandIsReadOnly(pstmt))
 				ereport(ERROR,
 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 CreateCommandTag((Node *) pstmt) == CMDTAG_SELECT ?
+						 errmsg("A WITH clause containing a data-modifying statement is not allowed in a non-volatile function")
 				/* translator: %s is a SQL statement name */
-						 errmsg("%s is not allowed in a non-volatile function",
-								CreateCommandName((Node *) pstmt))));
+						 : errmsg("%s is not allowed in a non-volatile function",
+								  CreateCommandName((Node *) pstmt))));
 		}
 	}
 
@@ -2631,9 +2633,11 @@ _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options,
 			if (options->read_only && !CommandIsReadOnly(stmt))
 				ereport(ERROR,
 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+						 CreateCommandTag((Node *) stmt) == CMDTAG_SELECT ?
+						 errmsg("A WITH clause containing a data-modifying statement is not allowed in a non-volatile function")
 				/* translator: %s is a SQL statement name */
-						 errmsg("%s is not allowed in a non-volatile function",
-								CreateCommandName((Node *) stmt))));
+						 : errmsg("%s is not allowed in a non-volatile function",
+								  CreateCommandName((Node *) stmt))));
 
 			/*
 			 * If not read-only mode, advance the command counter before each
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 30b51bf4d3..36179f8ef9 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -413,9 +413,11 @@ PreventCommandIfReadOnly(const char *cmdname)
 	if (XactReadOnly)
 		ereport(ERROR,
 				(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
+				 cmdname == NULL
+				 ? errmsg("A WITH clause containing a data-modifying statement is not allowed in a read-only transaction")
 		/* translator: %s is name of a SQL command, eg CREATE */
-				 errmsg("cannot execute %s in a read-only transaction",
-						cmdname)));
+				 : errmsg("cannot execute %s in a read-only transaction",
+						  cmdname)));
 }
 
 /*
