diff --git a/src/backend/catalog/pg_publication.c b/src/backend/catalog/pg_publication.c
index 200e5f7f71e..a0298d0f2a1 100644
--- a/src/backend/catalog/pg_publication.c
+++ b/src/backend/catalog/pg_publication.c
@@ -49,6 +49,29 @@ typedef struct
 								 * table. */
 } published_rel;
 
+/*
+ * Double any embedded double-quote characters in str, so that it is
+ * safe to interpolate into a message that itself wraps the result in
+ * literal double quotes (e.g. errmsg("relation \"%s\" ...", ...)).
+ * This does NOT decide whether quoting is needed, unlike
+ * quote_identifier() -- the caller's message always supplies the
+ * surrounding quotes itself.
+ */
+static char *
+escape_embedded_quotes(const char *str)
+{
+	StringInfoData buf;
+
+	initStringInfo(&buf);
+	for (const char *p = str; *p; p++)
+	{
+		if (*p == '"')
+			appendStringInfoChar(&buf, '"');	/* double it */
+		appendStringInfoChar(&buf, *p);
+	}
+	return buf.data;
+}
+
 /*
  * Check if relation can be in given publication and throws appropriate
  * error if not.
@@ -67,8 +90,8 @@ check_publication_add_relation(PublicationRelInfo *pri)
 		 * encloses the whole name in double quotes.
 		 */
 		relname = psprintf("%s.%s",
-						   get_namespace_name(RelationGetNamespace(targetrel)),
-						   RelationGetRelationName(targetrel));
+						   escape_embedded_quotes(get_namespace_name(RelationGetNamespace(targetrel))),
+						   escape_embedded_quotes(RelationGetRelationName(targetrel)));
 		errormsg = gettext_noop("cannot specify relation \"%s\" in the publication EXCEPT clause");
 	}
 	else
diff --git a/src/test/regress/expected/publication.out b/src/test/regress/expected/publication.out
index 8fc5d0d7c5a..57a51ffd7dc 100644
--- a/src/test/regress/expected/publication.out
+++ b/src/test/regress/expected/publication.out
@@ -471,9 +471,14 @@ ERROR:  cannot specify relation "public.testpub_part1" in the publication EXCEPT
 DETAIL:  This operation is not supported for individual partitions.
 -- A name that needs quoting must not be quoted twice in the message.
 CREATE TABLE "testpub Part2" PARTITION OF testpub_root FOR VALUES FROM (100) TO (200);
+CREATE SCHEMA "schema has embedded "" quotes";
+CREATE TABLE "schema has embedded "" quotes"."part has embedded "" quotes" PARTITION OF testpub_root FOR VALUES FROM (200) TO (300);
 CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "testpub Part2");
 ERROR:  cannot specify relation "public.testpub Part2" in the publication EXCEPT clause
 DETAIL:  This operation is not supported for individual partitions.
+CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "schema has embedded "" quotes"."part has embedded "" quotes");
+ERROR:  cannot specify relation "schema has embedded "" quotes.part has embedded "" quotes" in the publication EXCEPT clause
+DETAIL:  This operation is not supported for individual partitions.
 CREATE TABLE tab_main (a int) PARTITION BY RANGE(a);
 -- Attaching a partition is not allowed if the partitioned table appears in a
 -- publication's EXCEPT clause.
@@ -483,6 +488,7 @@ DETAIL:  The publication EXCEPT clause cannot contain tables that are partitions
 HINT:  Change the publication's EXCEPT clause using ALTER PUBLICATION ... SET ALL TABLES.
 RESET client_min_messages;
 DROP TABLE testpub_root, testpub_part1, "testpub Part2", tab_main;
+DROP SCHEMA "schema has embedded "" quotes" CASCADE;
 DROP PUBLICATION testpub8;
 --- Tests for publications with SEQUENCES
 CREATE SEQUENCE regress_pub_seq0;
diff --git a/src/test/regress/sql/publication.sql b/src/test/regress/sql/publication.sql
index 84f534c387a..11b849c9566 100644
--- a/src/test/regress/sql/publication.sql
+++ b/src/test/regress/sql/publication.sql
@@ -214,7 +214,10 @@ CREATE PUBLICATION testpub8 FOR ALL TABLES EXCEPT (TABLE testpub_root);
 CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE testpub_part1);
 -- A name that needs quoting must not be quoted twice in the message.
 CREATE TABLE "testpub Part2" PARTITION OF testpub_root FOR VALUES FROM (100) TO (200);
+CREATE SCHEMA "schema has embedded "" quotes";
+CREATE TABLE "schema has embedded "" quotes"."part has embedded "" quotes" PARTITION OF testpub_root FOR VALUES FROM (200) TO (300);
 CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "testpub Part2");
+CREATE PUBLICATION testpub9 FOR ALL TABLES EXCEPT (TABLE "schema has embedded "" quotes"."part has embedded "" quotes");
 
 CREATE TABLE tab_main (a int) PARTITION BY RANGE(a);
 -- Attaching a partition is not allowed if the partitioned table appears in a
@@ -223,6 +226,7 @@ ALTER TABLE tab_main ATTACH PARTITION testpub_root FOR VALUES FROM (0) TO (200);
 
 RESET client_min_messages;
 DROP TABLE testpub_root, testpub_part1, "testpub Part2", tab_main;
+DROP SCHEMA "schema has embedded "" quotes" CASCADE;
 DROP PUBLICATION testpub8;
 
 --- Tests for publications with SEQUENCES
