FerriteCore (Fabric)

FerriteCore (Fabric)

30M Downloads

Crash on startup - `FerriteConfig` hides exceptions raised in `ConfigFileHandler` by not unwrapping the underlying `InvocationTargetException`

alcatrazEscapee opened this issue ยท 3 comments

commented

Minecraft 1.20.1
Mod Loader Lex Forge
Forge 47.2.23
Ferrite Core 6.0.1
Crash Log https://paste.ee/p/ITjLM

This crash log is particularly hard to decipher, because the crash originates from here:

Caused by: java.lang.NoClassDefFoundError: Could not initialize class malte0811.ferritecore.mixin.config.FerriteConfig
...
Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.RuntimeException: java.lang.reflect.InvocationTargetException [in thread "main"]
	at TRANSFORMER/[email protected]/malte0811.ferritecore.mixin.config.FerriteConfig$ConfigBuilder.finish(FerriteConfig.java:100)
	at TRANSFORMER/[email protected]/malte0811.ferritecore.mixin.config.FerriteConfig.<clinit>(FerriteConfig.java:75)
	at TRANSFORMER/[email protected]/malte0811.ferritecore.mixin.predicates.Config.<init>(Config.java:8)

This appears because FerriteConfig tries to reflectively invoke a method, and then immediately wrap any exceptions thrown in a RuntimeException, it hides the underlying cause (which would be whatever error was thrown in the reflectively invoked method itself:

try {
// This runs too early for arch's ExpectPlatform, so reflection it is
Class<?> handler = Class.forName("malte0811.ferritecore.mixin.platform.ConfigFileHandler");
Method finish = handler.getMethod("finish", List.class);
finish.invoke(null, options);
} catch (Exception e) {
throw new RuntimeException(e);
}

Ideally, this should catch InvocationTargetExceptions, and throw a new RuntimeError(e.getCause()), as that would be the actual underlying error being thrown. Beyond that, FerriteCore is crashing on startup here with unclear cause, but the problem appears to be directly related to whatever ConfigFileHandler is doing, which seems to crash loading the mixin config plugin.

commented

Sorry, I have been very busy with other projects (with hard deadlines) as well as general IRL stuff recently. It seems that paste.ee deleted your log, can you reupload it somewhere else (e.g. gist) without an expiration period? Expiring log files are a problem especially for this sort of "unclear cause" issue: If I cannot work out the problem from the log, I may need to wait for someone else to run into the same issue and then look for similarities, which I cannot do if the first log has already expired.

commented

Sadly no, as this log, via this link, was given to me via a user - I didn't think at the time to reupload it somewhere else. I don't know what the underlying issue was, as my memory at the time was the fact it was a modpack with a huge mod count. I reported this issue because there is a very obvious problem here, namely the catch(Exception e) { throw new RuntimeException(e); }, should be catching InvocationTargetException and rethrowing the e.getTargetException() - the exception that actually occurred in the reflective access - which would make this issue, if it were to appear again, at least visible.

commented

Part of the problem is that unless your log was very different from the one I produced by intentionally throwing an exception, the stacktraces do not seem that problematic to me: The "real" exception was the lowest one (as usual in these situations), with multiple levels of rethrowing above it. What made my test log hard to follow was that the exception did not trigger a crash immediately, instead some later similar exception did. Changing the exception structure would not affect that. I will look into fixing that, but as a relatively low priority since it is still very obvious from the log that FerriteCore is involved "somehow".