Why do get_category_by_slug() crashes WordPress 4.8

Because get_category_by calls get_term_by which calls get_terms which creates a WP_Term_Query which runs the list_terms_exclusions filter, which runs your code that calls get_category_by which calls get_term_by which calls get_terms etc etc etc

Your problem is that of an infinite loop, the functions you call in your filter, trigger the filter they’re called in. It’s not that WordPress has changed, but rather that the filter should never have worked to begin with.

Solutions

Breaking The Loop

Unhook your filter before calling get_category_by, then hook it back in afterwards.

I’m not a big fan of this option

Changing from term ID to term slug/name

You don’t need to find which term ID has the name uncategorized, you’re already passing in SQL, so use t.slug <> 'uncategorized' or something to that effect

This is a bit better, but it still commits the fundamental sin of giving a NOT selector to MySQL. Those kinds of queries are fundamentally expensive and don’t scale, you should ask for what you want, not what you do not want.

Pulling the term out in PHP

When the terms are fetched, manually take out the term you don’t want in PHP afterwards. This is the most performant options, and scales the best. It’s also much more database friendly

That metabox specifically uses these 2 functions to display the terms:

  • wp_dropdown_categories
  • wp_terms_checklist

wp_dropdown_cats can be used to filter the final HTML output of wp_dropdown_categories although you could reach into get_terms and use its filters to remove the term before that point more efficiently. For details on how to do that, see this question/answer

This is my preferred solution

Remove the metabox and add your own

As long as the form inputs are the same as the standard metabox, you can replace it entirely, and there’ll be no need for save code.

I’m not a big fan of this solution as it could interfere with other plugins and has the largest effort required