diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index a1bb3e9..1ec60a1 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -354,6 +354,13 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 			 * adjustments will be needed below.
 			 */
 
+			if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE)
+				ereport(ERROR,
+						(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+						 errmsg("\"%s\" is a partitioned table",
+								RelationGetRelationName(rel)),
+					 errdetail("Triggers on partitioned tables cannot have transition tables.")));
+
 			if (stmt->timing != TRIGGER_TYPE_AFTER)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out
index f408475..4b0b3b7 100644
--- a/src/test/regress/expected/triggers.out
+++ b/src/test/regress/expected/triggers.out
@@ -1763,3 +1763,27 @@ select * from upsert;
 drop table upsert;
 drop function upsert_before_func();
 drop function upsert_after_func();
+--
+-- Verify that triggers are prevented on partitioned tables if they would
+-- access row data (ROW and STATEMENT-with-transition-table)
+--
+create table my_table (i int) partition by list (i);
+create table my_table_42 partition of my_table for values in (42);
+create function my_trigger_function() returns trigger as $$ begin end; $$ language plpgsql;
+create trigger my_trigger before update on my_table for each row execute procedure my_trigger_function();
+ERROR:  "my_table" is a partitioned table
+DETAIL:  Partitioned tables cannot have ROW triggers.
+create trigger my_trigger after update on my_table referencing old table as old_table
+   for each statement execute procedure my_trigger_function();
+ERROR:  "my_table" is a partitioned table
+DETAIL:  Triggers on partitioned tables cannot have transition tables.
+--
+-- Verify that triggers are allowed on partitions
+--
+create trigger my_trigger before update on my_table_42 for each row execute procedure my_trigger_function();
+drop trigger my_trigger on my_table_42;
+create trigger my_trigger after update on my_table_42 referencing old table as old_table
+   for each statement execute procedure my_trigger_function();
+drop trigger my_trigger on my_table_42;
+drop table my_table_42;
+drop table my_table;
diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql
index b6de1b3..4473ce0 100644
--- a/src/test/regress/sql/triggers.sql
+++ b/src/test/regress/sql/triggers.sql
@@ -1240,3 +1240,26 @@ select * from upsert;
 drop table upsert;
 drop function upsert_before_func();
 drop function upsert_after_func();
+
+--
+-- Verify that triggers are prevented on partitioned tables if they would
+-- access row data (ROW and STATEMENT-with-transition-table)
+--
+
+create table my_table (i int) partition by list (i);
+create table my_table_42 partition of my_table for values in (42);
+create function my_trigger_function() returns trigger as $$ begin end; $$ language plpgsql;
+create trigger my_trigger before update on my_table for each row execute procedure my_trigger_function();
+create trigger my_trigger after update on my_table referencing old table as old_table
+   for each statement execute procedure my_trigger_function();
+
+--
+-- Verify that triggers are allowed on partitions
+--
+create trigger my_trigger before update on my_table_42 for each row execute procedure my_trigger_function();
+drop trigger my_trigger on my_table_42;
+create trigger my_trigger after update on my_table_42 referencing old table as old_table
+   for each statement execute procedure my_trigger_function();
+drop trigger my_trigger on my_table_42;
+drop table my_table_42;
+drop table my_table;
