diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index edff54e734e..3a482a73ceb 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -314,6 +314,16 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 		PreventInTransactionBlock(isTopLevel, "REPACK (CONCURRENTLY)");
 	}
 
+	else if ((params.options & CLUOPT_ANALYZE) != 0)
+	{
+		/*
+		 * REPACK (ANALYZE) performs transaction management internally.
+		 * It therefore cannot be executed from a transaction block or
+		 * from a function.
+		 */
+		PreventInTransactionBlock(isTopLevel, "REPACK (ANALYZE)");
+	}
+
 	/*
 	 * If a single relation is specified, process it and we're done ... unless
 	 * the relation is a partitioned table, in which case we fall through.
diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql
index e7a62367adf..cb170731147 100644
--- a/src/test/regress/sql/cluster.sql
+++ b/src/test/regress/sql/cluster.sql
@@ -380,6 +380,10 @@ INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
 SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass
 ORDER BY 1;
 
+-- REPACK (ANALYZE) must not be executed inside a transaction block
+BEGIN;
+REPACK (ANALYZE) clstr_tst;
+ROLLBACK;
 -- Verify partial analyze works
 REPACK (ANALYZE) clstr_tst (a);
 REPACK (ANALYZE) clstr_tst;
