it simply narrows the search for a valid format.
That makes sense, but only when you're looking at a format in a vacuum. When you look at it as a tool for solving a problem, for fulfilling a need, it doesn't make as much sense.

If you have a need for a floating-point image, a fixed-point one will not work. That's why you decided you needed a floating-point one. If you need a 4-channel render target, an unrenderable format will not work. And so on.

Which means that, in the event of failing to create the preferred format, the number of usable alternatives is quite small. Indeed, it is something that you want to have explicit control over, not start blindly enumerating all possible formats. Most important of all, what makes the format usable is the intended use, which generally cannot be boiled down to an enumeration. So if you really need a 2048x2048x128fp format that supports being a render target, supports blending, and supports filtering, your method would be useless, because it would return a format that fills only some of those requirements.

Your pseudo-code is broken in precisely this way: it is ignorant of need.

If your code needs feature X, not getting it should mean a hard break. It should not mean, "Keep trying until you return something". It should stop, return an error, throw an exception, anything but return something valid.