Why is WordPress showing a blank excerpt for just one of my posts?

After a couple hours of debugging, here is what I figured out:

  • The unfortunately-named wp_trim_excerpt() does not merely trim the excerpt passed to it, but also assembles an excerpt if a blank string is passed in. (Yes, I see now that this is in the documentation, but I was grep’ing through code trying to trace what was being hooked into get_the_excerpt.)

  • The call to excerpt_remove_blocks() is the line within wp_trim_excerpt() which first returned a blank string.

  • excerpt_remove_blocks() goes through all the blocks in the post and filters out ones whose names are not on an approved list, called $allowed_inner_blocks, which is stored within the function.

  • Although in the editor my post appeared to be a normal post with paragraph and image blocks, all those blocks were secretly part of one big group block with the name core/group, which is not part of $allowed_inner_blocks. Thus, when excerpt_remove_blocks() looped over the blocks, it found one block of an unacceptable type and returned nothing.

  • But how would I have known about this group block?! I could find no indication in the block editor that all these blocks were grouped. The block editor worked as it always does, and I could add/delete/move blocks as usual with no issues. I could also create new groups out of existing blocks, but I could not undo this existing group or see any indication of its presence.

  • To remove the hidden group, I had to switch into the Code Editor from the Visual Editor. There, I saw the whole text of the post appeared like so:

    <!-- wp:group -->
    <div class="wp-block-group">
       <div class="wp-block-group__inner-container">
    
       ...
    
       </div></div>
    <!-- /wp:group -->
    
  • I deleted these lines, updated the post, and voila — now an excerpt appears as expected on the homepage of my blog.

As to how this group got in there in the first place — no earthly idea. But I hope this solution now shows up in search to save time for the next poor soul who encounters this situation.