Odd results in get_the_terms vs wp_get_post_terms

The primary difference between the two is that wp_get_post_terms is not cached and always goes straight to the database, in fact get_the_terms uses the same API internally, wp_get_post_terms is a wrapper around wp_get_object_terms, which is also used by get_the_terms but with caching and fewer configurable options.

However, this is an X Y question. You shouldn’t have asked how to solve your solution with the empty return value, but instead how to solve your problem, aka:

I get back an array of categories to use in a loop, etc. Only problem is that it’s in alphabetical order. (I want it in hierarchical order.)

There is no such thing as hierarchical order in these APIs.

To do this you will need to add a processing step or loops to iterate over the list of terms. e.g. for each term, if it has no parent, display it then loop over all terms in a nested loop displaying those that have this term as their parent, etc. Recursion will be needed if you want more than one layer of depth.

For performance reasons you should use get_the_terms.