diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 933dcbf500..604e35b761 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1659,6 +1659,56 @@ having_collation_conflict_walker(Node *node, having_collation_ctx *ctx)
 		return false;
 	}
 
+	if (IsA(node, CaseExpr) && ((CaseExpr *) node)->arg != NULL)
+	{
+		CaseExpr   *cexpr = (CaseExpr *) node;
+		ListCell   *lc;
+		int			pushed = 0;
+		bool		found;
+
+		/*
+		 * The shorthand CASE rewrites to OpExpr(placeholder = valN) per WHEN,
+		 * where arg holds the GROUP Var.  Push each WHEN's inputcollid before
+		 * recursing into arg so we detect collation conflicts there.
+		 */
+		foreach(lc, cexpr->args)
+		{
+			CaseWhen   *cw = lfirst_node(CaseWhen, lc);
+			Oid			collid = exprInputCollation((Node *) cw->expr);
+
+			if (OidIsValid(collid))
+			{
+				ctx->ancestor_collids = lappend_oid(ctx->ancestor_collids,
+													collid);
+				pushed++;
+			}
+		}
+
+		found = having_collation_conflict_walker((Node *) cexpr->arg, ctx);
+
+		while (pushed-- > 0)
+			ctx->ancestor_collids =
+				list_delete_last(ctx->ancestor_collids);
+
+		if (found)
+			return true;
+
+		/* Walk WHEN expressions, results, and defresult normally. */
+		foreach(lc, cexpr->args)
+		{
+			CaseWhen   *cw = lfirst_node(CaseWhen, lc);
+
+			if (having_collation_conflict_walker((Node *) cw->expr, ctx))
+				return true;
+			if (having_collation_conflict_walker((Node *) cw->result, ctx))
+				return true;
+		}
+		if (having_collation_conflict_walker((Node *) cexpr->defresult, ctx))
+			return true;
+
+		return false;
+	}
+
 	this_collid = exprInputCollation(node);
 	if (OidIsValid(this_collid))
 		ctx->ancestor_collids = lappend_oid(ctx->ancestor_collids,
diff --git a/src/test/regress/expected/collate.icu.utf8.out b/src/test/regress/expected/collate.icu.utf8.out
index 8c3a369e21..a6d81deecd 100644
--- a/src/test/regress/expected/collate.icu.utf8.out
+++ b/src/test/regress/expected/collate.icu.utf8.out
@@ -2261,6 +2261,51 @@ SELECT x, count(*) FROM test3ci GROUP BY x HAVING current_setting('server_versio
          ->  Seq Scan on test3ci
 (5 rows)
 
+-- Negative: collation conflict hidden inside shorthand CASE
+EXPLAIN (COSTS OFF)
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_sensitive THEN true ELSE false END;
+                                   QUERY PLAN                                    
+---------------------------------------------------------------------------------
+ HashAggregate
+   Group Key: x
+   Filter: CASE x WHEN 'abc'::text COLLATE case_sensitive THEN true ELSE false END
+   ->  Seq Scan on test3ci
+(4 rows)
+
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_sensitive THEN true ELSE false END;
+  x  | count 
+-----+-------
+ abc |     2
+(1 row)
+
+-- Positive: shorthand CASE with matching collation, safe to push
+EXPLAIN (COSTS OFF)
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_insensitive THEN true ELSE false END;
+                                      QUERY PLAN                                       
+---------------------------------------------------------------------------------------
+ HashAggregate
+   Group Key: x
+   ->  Seq Scan on test3ci
+         Filter: CASE x WHEN 'abc'::text COLLATE case_insensitive THEN true ELSE false END
+(4 rows)
+
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_insensitive THEN true ELSE false END;
+  x  | count 
+-----+-------
+ abc |     2
+(1 row)
+
+-- Negative: nested CASE with collation conflict
+EXPLAIN (COSTS OFF)
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE WHEN CASE x WHEN 'abc' COLLATE case_sensitive THEN 1 ELSE 0 END = 1 THEN true ELSE false END;
+                                                    QUERY PLAN                                                     
+-------------------------------------------------------------------------------------------------------------------
+ HashAggregate
+   Group Key: x
+   Filter: CASE WHEN (CASE x WHEN 'abc'::text COLLATE case_sensitive THEN 1 ELSE 0 END = 1) THEN true ELSE false END
+   ->  Seq Scan on test3ci
+(4 rows)
+
 -- Positive: deterministic collation in GROUP BY: always safe to push, even if
 -- HAVING uses a nondeterministic collation
 EXPLAIN (COSTS OFF)
diff --git a/src/test/regress/sql/collate.icu.utf8.sql b/src/test/regress/sql/collate.icu.utf8.sql
index fdcdb2094f..20de47030f 100644
--- a/src/test/regress/sql/collate.icu.utf8.sql
+++ b/src/test/regress/sql/collate.icu.utf8.sql
@@ -801,6 +801,20 @@ SELECT x, count(*) FROM test3ci GROUP BY x HAVING ROW(x, 1) < ROW('ABC' COLLATE
 EXPLAIN (COSTS OFF)
 SELECT x, count(*) FROM test3ci GROUP BY x HAVING current_setting('server_version') = 'abc' COLLATE case_sensitive;
 
+-- Negative: collation conflict hidden inside shorthand CASE
+EXPLAIN (COSTS OFF)
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_sensitive THEN true ELSE false END;
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_sensitive THEN true ELSE false END;
+
+-- Positive: shorthand CASE with matching collation, safe to push
+EXPLAIN (COSTS OFF)
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_insensitive THEN true ELSE false END;
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE x WHEN 'abc' COLLATE case_insensitive THEN true ELSE false END;
+
+-- Negative: nested CASE with collation conflict
+EXPLAIN (COSTS OFF)
+SELECT x, count(*) FROM test3ci GROUP BY x HAVING CASE WHEN CASE x WHEN 'abc' COLLATE case_sensitive THEN 1 ELSE 0 END = 1 THEN true ELSE false END;
+
 -- Positive: deterministic collation in GROUP BY: always safe to push, even if
 -- HAVING uses a nondeterministic collation
 EXPLAIN (COSTS OFF)
