Linux has non-standard UDP error semantics (see bug 202355), and the decision is "that is how Linux works".
RFC1122 section 126.96.36.199 says that all ICMP errors should be reported to the application layer. Linux follows the BSD convention of only reporting errors for connect()ed sockets, but Linux *also* has extra code that will *not* report errors to the application if it's a Destination Host Unreachable, Destination Net Unreachable, Source Route Failed, or Fragmentation Required *unless* you also set IP_RECVERR / IPV6_RECVERR.
The manpages describe IP_RECVERR as only providing additional information to application, which is true, but as a side effect it also reports *all* errors to the application. If you want to also receive "transient" error messages, then you must also set IP_RECVERR.
This is very poorly understood, even by Linux experts, for example, see the thread https://lists.dns-oarc.net/pipermail/dns-operations/2019-January/018271.html, https://sourceware.org/bugzilla/show_bug.cgi?id=24047,
Please add some clarifying text to the udp(7) manpage, describing that if you want to also receive "transient" ICMP errors (Destination Net/Host Unreachable, Source Route failed, or Fragmentation Required), then you must also set IP_RECVERR or IPV6_RECVERR (as appropriate).