Crashes during very early Minecraft initialization are not properly handled
In Main.main(), there are a few initialization routines that are not surrounded with a try/catch block. If a crash occurs in these methods, Main.main() throws an exception. Fabric Loader does not anticipate an exception and never catches it, so the exception makes its way all the way to the top of the stack.
As it turns out, this unhandled exception does not get printed to the log file and no crash report is generated. MultiMC displays it in the log box, at least, but I'm not sure if the vanilla launcher handles it. This results in very cryptic crashes that are nearly impossible for a 3rd party to debug without replicating the entire mods setup on their end.
At a minimum, Fabric Loader should catch any unhandled exceptions from Main.main(), print them to the log, and bring up the error GUI.
However, if possible, it would be nice if a proper crash report was generated even for these types of crashes. In my case, an exception happened in Bootstrap.initialize(), which happens right after the crash report infrastructure is set up.
There is an expectation that an exception might propagate up from the game, but only Exception (so your generic Throwable, Error, etc. will leak out):
https://github.com/FabricMC/fabric-loader/blob/62dec491951127559a597ea13bd0194ced70fe6a/src/main/java/net/fabricmc/loader/game/MinecraftGameProvider.java#L215-L230
Of course this is hardly handling it much better, but there is at least a suitable place to handle the issue.
"The log" becomes a little bit of an issue in and of itself as some versions of Minecraft don't even have one, and the ones that do don't redirect the standard out/error until Bootstrap#setOutputStreams (which is the final call of Bootstrap#initialize). Whilst Loader includes Log4J via Mixin it can make its own to get around this, but there was talk of removing it as a dependency given games might be using a different logging system. A GUI would probably be more user friendly anyway, but that leaves Mac users out using AWT.
On balance the best option is probably still FabricGuiEntry#displayCriticalError as it uses the Loader logger + GUI system which is about as good as we have. For making actual crash reports either Loader will have to make its own, or have an interface similar to Thread's UncaughtExceptionHandler to allow something like Fabric API to push it over to Minecraft's own crash reporter to have a go.
Hmm, since fabric loader calls main by reflection, isn't any throwable from there wrapped in an invocation target exception than be thrown directly as in method handles? https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/reflect/Method.html#invoke(java.lang.Object,java.lang.Object...)
That code will catch the InvocationTargetException that occurs, but it just rethrows it as a RuntimeException which doesn't really help. In fact, it's worse since it's less likely that anything will catch the resulting exception.
Hmm, if game falters before launch, where do the sys out stuff go to?
Hmm, since fabric loader calls main by reflection, isn't any throwable from there wrapped in an invocation target exception than be thrown directly as in method handles? https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/lang/reflect/Method.html#invoke(java.lang.Object,java.lang.Object...)
Thinking about it, yes anything from Minecraft would be wrapped in that. If you happened to set the heap size to something impractically small (thinking low double digit MBs at most) you could possibly still have an out of memory error from the reflection code itself but that's a pretty silly edge case.
That code will catch the InvocationTargetException that occurs, but it just rethrows it as a RuntimeException which doesn't really help. In fact, it's worse since it's less likely that anything will catch the resulting exception.
The only code in a position to catch exceptions which throw from that point is Loader's (which doesn't as it stands), and any parent code which invoked Knot itself. Given the vanilla launcher seems pretty good at eating unchecked exceptions it receives directly that would suggest it wouldn't handle checked exceptions any better. Moral of the story is propagating anything up is launcher dependent to whether it's actually handled further.
Hmm, if game falters before launch, where do the sys out stuff go to?
Straight to the default standard out/err. It would also be launcher dependent to whether it captures it (which MultiMC does for example but the vanilla launcher appears not to).
So fabric loader would act as a secondary launcher that reports its own errors, I assume.
More that it should provide platform independent exception handling, you can't trust that whatever launched Loader is going to do it in a useful way. I'd also say this is more of an enhancement rather than question tag wise.
This has had a fix merged in with c12adfb. There is still the question of what to do when Loader itself crashes before getting to starting mods (it is launcher dependent whether those crashes are recorded/presented to the user) but that might be better in a new issue to consider whether there needs to be wider changes to things like the exception types thrown.