--- a/net/minecraft/network/chat/contents/TranslatableContents.java
+++ b/net/minecraft/network/chat/contents/TranslatableContents.java
@@ -181,6 +_,16 @@
 
     @Override
     public <T> Optional<T> visit(FormattedText.ContentConsumer<T> contentConsumer) {
+        // Paper start - Count visited parts
+        try {
+            return this.visit(new TranslatableContentConsumer<>(contentConsumer));
+        } catch (IllegalArgumentException ignored) {
+            return contentConsumer.accept("...");
+        }
+    }
+
+    private <T> Optional<T> visit(TranslatableContentConsumer<T> contentConsumer) {
+        // Paper end - Count visited parts
         this.decompose();
 
         for (FormattedText formattedText : this.decomposedParts) {
@@ -192,6 +_,27 @@
 
         return Optional.empty();
     }
+
+    // Paper start - Count visited parts
+    private static final class TranslatableContentConsumer<T> implements FormattedText.ContentConsumer<T> {
+        private static final IllegalArgumentException NESTED_TOO_LONG = new IllegalArgumentException("Too long");
+
+        private final FormattedText.ContentConsumer<T> visitor;
+        private int visited;
+
+        private TranslatableContentConsumer(final FormattedText.ContentConsumer<T> visitor) {
+            this.visitor = visitor;
+        }
+
+        @Override
+        public Optional<T> accept(final String asString) {
+            if (this.visited++ > 32) {
+                throw NESTED_TOO_LONG;
+            }
+            return this.visitor.accept(asString);
+        }
+    }
+    // Paper end - Count visited parts
 
     @Override
     public MutableComponent resolve(@Nullable CommandSourceStack nbtPathPattern, @Nullable Entity entity, int recursionDepth) throws CommandSyntaxException {
