JIT Exception - tModLoader/tModLoader GitHub Wiki

What are JIT Exceptions?

In an effort to avoid silent errors caused by tModLoader updating frequently and mods becoming "out-of-date", tModLoader now inspects all classes and methods of each mod as it loads, checking that it can work properly.

tModLoader developers strive to avoid these types of issues through careful programming, but sometimes these issues are unforeseen or unavoidable.

Player Instructions

The mod is broken, you'll need to wait for the mod to update. It is possible the author does not know the mod is broken or does not wish to continue updating the mod. You can check the mods preferred feedback location to see if you can find more information or inform the author of the issue if no one else has reported the issue. Typically mods have a GitHub Issue tracker, a Discord server, or the mod's Steam Workshop page as their preferred feedback location.

Modder Instructions

You need to update your mod. Most of the time these errors happen because tModLoader changed and your mod has not updated. For example, if a tModLoader method changes, your mod will be broken because it is trying to use a method that no longer exists. The other possibility is that your mod uses strong or weak references and recent tModLoader changes dictate that you will need to further annotate some methods or classes in your mod to accommodate.

tModLoader Changed

You'll need to change the code in your mod to fix all the errors now present and publish a release. The first step is to run tModPorter from the ModSources menu. This should fix most errors. There will be some errors remaining that have new comments added by tModPorter, you'll need to fix those remaining errors according to the commented instructions. There are some changes that won't be handled by tModPorter. The #preview-update-log channel on the tModLoader Discord is where we track breaking changes introduced in the tModLoader Preview in anticipation for each months stable update. There will usually be Porting Notes listed for changes that could break existing mods. The Update Migration Guide is also updated occasionally. There is a slight possibility that there are no errors in Visual Studio, but your original published mod fails to load. In this case, building the mod and publishing again should fix the issue. This is typically caused by a new optional argument being added to a method you were previously using.

tModLoader Changed Example

Here is a typical JITException message, this example will go through interpreting and fixing this specific error:
image
First, we see at the top the the mod causing the error is called "BannerBonanza". In the next section, we see the actual JITException message, it says that:

In BannerBonanza.Items.BannerRackItem.SetDefaults, Method not found: 'Void Terraria.Item.DefaultToPlacableWall(UInt16)'."

From this, we know that in the BannerRackItem class in the BannerBonanza.Items namespace, the SetDefaults method is where this particular error is happening. The error says that the method Void Terraria.Item.DefaultToPlacableWall(UInt16) doesn't exist. When this mod was built, the method did exist, but apparently it doesn't anymore.

At this point, you could check the #preview-update-log channel on the tModLoader Discord and look for recent messages talking about this. Here is an example of what that would look like:
image

At this point, open up Visual Studio and navigate to the location of the error. You should be able to immediately see red underlines indicating an error:
image
Using the information provided in the update log message or other methods, fix the error by changing DefaultToPlacableWall to DefaultToPlaceableWall. (Notice the missing "e" in the original "Placeable" spelling.)

This quick example should teach the basic steps for fixing JIT Exceptions, but feel free to come by the #mod-programming-help channel if you have trouble figuring out how to fix your issue. There is a slight possibility that there are no errors in Visual Studio, but your original published mod fails to load. In this case, building the mod and publishing again should fix the issue. This is typically caused by a new optional argument being added to a method you were previously using.

Strong References

If you get this error with a strongly referenced mod, most likely that mod changed. Extract the latest .dll from that mod and reference the newer .dll file in visual studio instead of the older one. Make sure to update build.txt to reference at least that version number using modReferences = [email protected]. Next, fix the errors and publish an update.

Weak References

The other possible cause of a JITException is a weak reference to another mod. When the game inspects all classes looking for errors, it'll trigger JITException for references to other mods that can't be resolved. You'll need to annotate classes with special attributes to tell tModLoader to skip attempting to inspect these classes. [JITWhenModsEnabled(...)] excludes a class/method/property from the load time JIT. Use this on any member which directly references a type from a mod that may not be present. Provide the mod names that all need to be loaded to allow the inspection. Here are some examples in a fictional mod ExampleModDepTest:

public class ExampleModCalls
{
    [JITWhenModsEnabled("ExampleMod")]
    public static int property => ModContent.ItemType<ExampleItem>();

    [JITWhenModsEnabled("ExampleMod")]
    public ExampleModCalls()
    {
        ModContent.GetInstance<ExampleModConfig>().ExampleWingsToggle = true;
    }

    [JITWhenModsEnabled("ExampleMod")]
    public static void method()
    {
        ModContent.GetInstance<ExampleModConfig>().ExampleWingsToggle = true;
    }

    [JITWhenModsEnabled("ExampleMod")]
    public static Action lambda()
    {
        return [JITWhenModsEnabled("ExampleMod")] () => ModContent.GetInstance<ExampleModConfig>().ExampleWingsToggle = true;
    }
}

[JITWhenModsEnabled("ExampleMod")]
public class SeparateClass
{
    public ExampleItem item = ModContent.GetInstance<ExampleItem>();

    public static ExampleModConfig method() => ModContent.GetInstance<ExampleModConfig>();

    public static Func<ExampleModConfig> lambda() => () => ModContent.GetInstance<ExampleModConfig>();
}

If you have special circumstances, you can use the NoJIT attribute on a class/method/property to skip the JIT process altogether. If you need more control, you can create a custom subclass of MemberJitAttribute or set Mod.PreJITFilter to a custom override. Note that the base implementation of ShouldJIT checks for MemberJitAttribute.

These annotations do not exempt you from properly gating calls to methods with references to Types in weakly referenced mods as taught in the Expert Cross Mod Content guide.