diff --git a/doc/src/sgml/ref/repack.sgml b/doc/src/sgml/ref/repack.sgml
index 0cb72b6b289..d9c7c9e6b95 100644
--- a/doc/src/sgml/ref/repack.sgml
+++ b/doc/src/sgml/ref/repack.sgml
@@ -329,6 +329,8 @@ REPACK [ ( <replaceable class="parameter">option</replaceable> [, ...] ) ] USING
      <para>
       Applies <xref linkend="sql-analyze"/> on the table after repacking.  This is
       currently only supported when a single (non-partitioned) table is specified.
+      This option cannot be used inside a transaction block, or from a function,
+      procedure, or <command>DO</command> block.
      </para>
     </listitem>
    </varlistentry>
diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index edff54e734e..c1ee5cdd37f 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -314,6 +314,15 @@ ExecRepack(ParseState *pstate, RepackStmt *stmt, bool isTopLevel)
 		PreventInTransactionBlock(isTopLevel, "REPACK (CONCURRENTLY)");
 	}
 
+	else if ((params.options & CLUOPT_ANALYZE) != 0)
+	{
+		/*
+		 * REPACK (ANALYZE) is not allowed in a transaction block for now,
+		 * consistently with VACUUM (FULL, ANALYZE).
+		 */
+		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/expected/cluster.out b/src/test/regress/expected/cluster.out
index d1bc8a13286..9ad7e2e21c0 100644
--- a/src/test/regress/expected/cluster.out
+++ b/src/test/regress/expected/cluster.out
@@ -796,9 +796,23 @@ ORDER BY 1;
  clstr_tst_pkey
 (3 rows)
 
--- Verify partial analyze works
+-- Verify REPACK (ANALYZE) works, including partial analyze.
 REPACK (ANALYZE) clstr_tst (a);
 REPACK (ANALYZE) clstr_tst;
+-- Plain REPACK is allowed in a transaction block.
+BEGIN;
+REPACK clstr_tst;
+ROLLBACK;
+-- REPACK (ANALYZE) is not allowed in a transaction block.
+BEGIN;
+REPACK (ANALYZE) clstr_tst;
+ERROR:  REPACK (ANALYZE) cannot run inside a transaction block
+ROLLBACK;
+-- REPACK (ANALYZE) is not allowed from a function.
+DO $$ BEGIN EXECUTE 'REPACK (ANALYZE) clstr_tst'; END $$;
+ERROR:  REPACK (ANALYZE) cannot be executed from a function or procedure
+CONTEXT:  SQL statement "REPACK (ANALYZE) clstr_tst"
+PL/pgSQL function inline_code_block line 1 at EXECUTE
 REPACK (VERBOSE) clstr_tst (a);
 ERROR:  ANALYZE option must be specified when a column list is provided
 -- REPACK w/o argument performs no ordering, so we can only check which tables
diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql
index e7a62367adf..dcc91e73698 100644
--- a/src/test/regress/sql/cluster.sql
+++ b/src/test/regress/sql/cluster.sql
@@ -380,9 +380,23 @@ INSERT INTO clstr_tst (b, c) VALUES (1111, 'this should fail');
 SELECT conname FROM pg_constraint WHERE conrelid = 'clstr_tst'::regclass
 ORDER BY 1;
 
--- Verify partial analyze works
+-- Verify REPACK (ANALYZE) works, including partial analyze.
 REPACK (ANALYZE) clstr_tst (a);
 REPACK (ANALYZE) clstr_tst;
+
+-- Plain REPACK is allowed in a transaction block.
+BEGIN;
+REPACK clstr_tst;
+ROLLBACK;
+
+-- REPACK (ANALYZE) is not allowed in a transaction block.
+BEGIN;
+REPACK (ANALYZE) clstr_tst;
+ROLLBACK;
+
+-- REPACK (ANALYZE) is not allowed from a function.
+DO $$ BEGIN EXECUTE 'REPACK (ANALYZE) clstr_tst'; END $$;
+
 REPACK (VERBOSE) clstr_tst (a);
 
 -- REPACK w/o argument performs no ordering, so we can only check which tables
