godot: .NET: Failed to unload assemblies. Please check for more information.
Godot version
Any 4.x version
Issue description
Assembly reloading can fail for various reasons, usually because a library used in tools code is not compatible with assembly unloading.
After unloading has failed, C# scripts will be unavailable until the editor is restarted (in rare cases it may be possible to complete the unloading by re-building assemblies after some time).
If assembly unloading fails for your project check Microsoft’s troubleshooting instructions and ensure that you are not using one of the libraries known to be incompatible:
- https://github.com/JamesNK/Newtonsoft.Json/issues/2414
- https://github.com/dotnet/runtime/issues/65323
If you know of additional libraries that cause issues, please leave a comment. If your code doesn’t use any libraries, doesn’t violate any guidelines and you believe unloading is blocked by godot, please open a new issue. Already reported causes are:
- https://github.com/godotengine/godot/issues/79519
- https://github.com/godotengine/godot/issues/80175 [^1]
- https://github.com/godotengine/godot/issues/81903
- https://github.com/godotengine/godot/pull/90837 [^1]
Minimal reproduction project & Cleanup example
using Godot;
using System;
[Tool]
public partial class UnloadingIssuesSample : Node
{
public override void _Ready()
{
// block unloading with a strong handle
var handle = System.Runtime.InteropServices.GCHandle.Alloc(this);
// register cleanup code to prevent unloading issues
System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(System.Reflection.Assembly.GetExecutingAssembly()).Unloading += alc =>
{
// handle.Free();
};
}
}
[^1]: Bugsquad edit
About this issue
- Original URL
- State: open
- Created a year ago
- Reactions: 49
- Comments: 91 (31 by maintainers)
Links to this issue
Commits related to this issue
- try to prevent assembly reload errors by not having multiple classes in one file, remove dependency on Newtonsoft.JSON, using System.Text.Json with cache clearing workaround (re godotengine/godot#7851... — committed to YarnSpinnerTool/YarnSpinner-Godot by dogboydog 9 months ago
- Try to prevent assembly reload errors (#12) * try to prevent assembly reload errors by not having multiple classes in one file, remove dependency on Newtonsoft.JSON, using System.Text.Json with cach... — committed to YarnSpinnerTool/YarnSpinner-Godot by dogboydog 9 months ago
I don’t know what is going on or why but I started getting this error today in Godot 4.1.1 .NET version. It’s completely blocking me from doing any development. I’ve spent all day trying to hunt down weird behaviors. It seems that when this issue happens it’s corrupting properties in the editor - or possibly inherited scenes are breaking. Restarting the editor is good for one run. But I keep constantly having to restart. This is 100% blocking all game development for me.
Without fixing this bug, the use of version 4.1.x is significantly limited and currently not recommended. We are using 4.0 until this is fixed, but are mourning the new features of 4.1 that we would have loved to use. Hopefully a fix in 4.2?
Also happens whenever I enable a C# editor plugin, and only goes away once I disable the plugin and restart the editor.
I am hitting this issue and I’m fairly confident it is not my (direct) fault.
I can reliably cause this error to appear in the console by running a C# rebuild while an offending Scene is loaded in the editor:
If I build again, I will get the “Failed to unload assemblies” error. If I close the offending scene and run the rebuild again, I rebuild without any issues and everything is fine.
I’ve been trying to figure out precisely what’s needed to get this problem to repro. It seems connected to the new
[GlobalClass]
attribute and resources, but not necessarily on a one-to-one basis.I got this while using Newtonsoft. I would really appreciate this having high priority, as this is quite a breaking bug. Are there plans to address this? Also, can someone explain to me in laymen’s terms how to just get my project not to scream at me when using newtonsoft? Is there a bit of code I can just tack onto the end of my JSON manager class? I saw the bit about on load but unsure of the context this is used
Even after removing all initial values off properties and fields, I am still seeing this issue when developing C# editor plugins and tool scripts.
I realize that I am not adding a lot to the conversation – just wanted to document that I could not verify the suggested fix on the 4.2 dev versions (macOS).
Godot 4.2.1. I keep getting “.NET: Failed to unload assemblies.” in tool scripts randomly, this completely blocks my work. Nothing of the mentioned above sheds light on what is the problem. No idea how to determinate the problem or reproduce it on demand. It’s a dead end making Godot NET unusable.
I am not using
Json.NET
orSystem.Text.Json
, and I am experiencing this issue. In the worst case, it results in data loss as serialized properties from C# Node scripts are reset todefault
.The only library I am referencing is one I have authored. My
.csproj
file looks like this:That project’s csproj is dead simple, with no other project references.
@RedworkDE, you mentioned “does not violate any guidelines”; what are these guidelines? Is there a documentation page? Something else? Thanks.
There are quite a few possible issues causing assemblies to fail to unload.
Some are out of our control.
dynamic
are known to be basically incompatible with assembly unloading.Some are bugs in Godot. As of now, the following have been identified.
I’ll edit if I remember other linked issues.
Your issue is related with #79519, a temporary fix (#86305) exits, I will try to validate if the fix works with the project you shared. This blocking issue affects every 4.x versions, which I think is crucial to fix before anyone starts working on a large-scale project in C#.
Can confirm that #86305 does fix the issue (Generic Class Duplicate Entries).
Here are patched version of GodotSharp.dll that includes the fix. Do remember to backup your project/editor to prevent data loss. 4.2.1.zip 4.2.0.zip cc @Luminoth
There are multiple causes of this problem. From the comments, there are at least three ways you can run into the issue…
I think I figured out what was causing it for me. It wasn’t editor plugins, global classes, or tool scripts. No, it’s because I had more than one Node class in a single script file.
Once I moved
PlayerState
to a separate file, the issue stopped happening.In case this is relevant, there are other node classes(such as
PlayerFlyState
) that inheritPlayerState
. Those nodes exist as children of the player node, and they get enabled/disabled as the player changes states.Thank you! I can confirm that the new version has indeed fixed this issue.
It’s not in 4.3.dev5, it will be in dev6 which should release in a few days
This is wild, I can’t build and run more than once on our GGJ code (https://github.com/pdxparrot/ggj2024) without running into this. I’m having to restart the editor every time I do anything and if I don’t then it corrupts whatever scene I was working on. This is making 4.2 unusable, is there any way to escalate this as a full on show stopper problem?
Huge thanks @Rylius! I was in the exact same case where I used to initialize my exported properties like this:
Removing the initialization from the code and doing it in the editor with the inspector instead worked like a charm! The issue in my project is gone now. Custom resources I have made so far were annotated with both
[Tool]
and[GlobalClass]
if it helps.Thanks for the info, I somehow missed that.
As an FYI, I played around with your solution trying it on a
EditorPlugin
derived class, but didn’t find it reliable in on_Ready
. As far as I could tell (or maybe I tested it wrong), rebuilding would reload the C# project but not re-invoke _Ready causing the error on subsequent rebuilds since the ‘new’ Unloading event is not registered (I assume because the node itself is not removed and re-added).My solution was to place the code within a
[ModuleInitializer]
method, ie:This ensures it is not dependent on any node(s) and is always registered only once, and re-registered upon reloading the assembly.
I’m very sorry, I found that I didn’t compile the mono version of godot through the correct process. At present, I don’t know how to compile GodotSharp, so I directly copied the old GodotSharp folder and used it with the new godot binary, so my test results is not credible.
I will try again when 4.3-dev6 is officially released.
This is my test code:
My testing process is:
This issue has been bothering me for a long time. Today I found the root cause through continuous attempts. It is caused by the use of anonymous functions when binding signals!
Can we please recentre on topic please? This thread is already very long, the future GDExtension implementation is unrelated to the issue at hand here.
FWIW, the error you’re experiencing is due to the deserialization of callables happening late after the state of your objects is restored. I have already started to look at how we could fix those timing issues during our assembly reload process last week. I need to run more tests on exactly how to improve this without changing the current behaviour.
AFAIK all the obvious cases we have highlighted until now should be fixed now.
Probably yes, because the C# script must also be tool code in order to be able to access its properties from GDScript.
@Luminoth
My suggestion is to add the editor itself into the version control system so that any file changes can appear and automatically update to the latest version when they merge your commit. But do remember that this patch is not yet accepted into the mainstream, and we have not thoroughly tested it, issues may occur, so do remember to make backups.
I have a weird bug when “Failed to unload assemblies” happen. My currently open scene will be resaved with weird or null value in the field. Example of corrupted value:
I mostly report this error for search result purpose. If I have time, I will try to make a repro project.
I just want to add to this that on 4.2 I also had this same issue with the following code in a custom resource:
The fix as @Rylius said is as follows:
I then init the export either through editor or from an init function. It’s worth noting that this resource is not marked as [Tool] or [GlobalClass], just a normal resource script.
Thanks for the workaround!
@RedworkDE Could you maybe edit #81903 into the initial post? It seems to be a reliable way to trigger this issue.
@kordian-kowalski looks like #81903
Yes. I’ve gone through my commit history one by one to figure out what caused this issue (somehow didn’t happen immediately/might not have edited any code for a few commits) and everything was fine just before I added the
new()
(the GlobalClass resources existed for several weeks before that). Removing it immediately fixed the issue. Withnull!
the inspector just shows “<empty>” (as expected), and assigning a new resource or loading an existing saved one work perfectly fine.Slight update. I’m just guessing here, but I suspect the issue might be somehow related to the new GlobalClass. That’s all I can think of. I got rid of the errors by deleting a node which had either been added via GlobalClass node or it was a regular node with the same script attached to it. Either way, I deleted it and the error was gone. I added it back in as GlobalClass node - the error stayed gone. Maybe this is helpful or maybe it is not, but I thought I’d mention it. It was a nightmare to track down.
@Tichau If possible, can you publish an issue about this, and, include a MRP (minimal reproducible project) for this issue you are encountering? Or, just share the code snippet that causes the issue?
See the .Net specific page for Compiling the Engine.
This issue has fixed in 4.3 you may try it out if the fix works. https://github.com/godotengine/godot/pull/83217
If possible, can you publish an issue about this, and, include a MRP (minimal reproducible project) for this issue you are encountering?
I got the assembly unload error about 2-ish weeks ago after working in the Godot editor for quite a while on various scenes in a row and hit the build button as I needed to assign some new properties I had just added. That was after I fixed obvious cases in my code where I ended up initializing static variables due to autoloads running in the editor. So there likely isn’t easily triggerable bug left in Godot that makes this issue show up, but it seems plausible there is still some way to end up triggering this issue. I can’t remember if I had already switched to 4.2.2 RC 2.
After finding this I noticed this error appear while VSCode is open. Closing it stopped the errors. And, It did seem to start after I tried setting up a debugging environment in VSCode (unsuccessfully), now I’m trying to figure out how to revert what I did 😕
I found asituation that would trigger this issue almost 100%,. MemroyPack is agood library, it’s Aot friendly, and it won’t have any problens with the editor when used in Godot,but once you use a serialized data type with a [MemoryPackable] annotation as a member field of Godot script that inherits from node or its subclasses, it will cause Godot to be unable to uninstall them.
example: &------------------------------------------------ namespace GodotDieFlowerUI { public partial class Graphics : Panel {
& -------------------------------------- using MemoryPack;
namespace godotDieFlowerImplement { [MemoryPackable] public partial struct Resolution
therefore, to be on the safe side,it is best to isolate all intrusive code from external libraries.
Newtonsoft is a better solution, it’s what I use. Installing it is very easy as well.
So here’s a strange one:
I get immediate assembly unload in an empty project with just a simple
GD.Print("Hello world");
in the_Ready
function once I build the project twice.But only if I start the executable
Godot_v4.1.2-stable_mono_linux.x86_64
directly in KDE by double clicking. If I drop to a terminal and do./Godot_v4.1.2-stable_mono_linux.x86_64
- no more assembly unloading.Is there a reason why no attached console could cause this?
Just wanting to add more to this conversation. I definitely started running into this issue when using the [GlobalClass] attribute. More specifically when I used this on Resource Classes that utilize generic variables. Once I determined the issue in my case I would restart the editor and the error would not be present. Everything seemed to work as expected unless I edit the scripts that either implement [GlobalClass] and or scripts that utilize [Export] of those resources. Not ideal but It would result in me restarting the editor and continuing on with my work. I am wondering what are the implications on builds is this just an issue with the editor? Im still early on in my project and want to know if I should rework the scripts / remove the [GlobalClass] attribute and just assign the script to an instanced resource as the work around.
CORRECTION: After further investigation, it doesn’t matter what scripts I edit. I receive this error anytime I edit a script and click build. It seems that as long as I am not trying to EXPORT any variables / anything that affects the editor directly the changes still save, and I am able to run the game without issue. So I am finding I only need to reload the project if the editor needs to be updated.
I added generic nodes today, and I started getting this issue.
Yeah, it seems that’s the root cause. That would be very unfortunate if true. I have a micro reproduction project and I’ll write up another issue. It runs fine but for the occasional compilation issue.
You also seem to be using generic
Node
s which also cause issues in some cases, see https://github.com/godotengine/godot/pull/79007