godotengine/godot

.NET: Failed to unload assemblies. Please check <this issue> for more information.

RedworkDE opened this issue · 100 comments

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:

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:

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();
        };
    }
}

Footnotes

  1. Bugsquad edit 2

Something was wrong with one of my [Tool] class in code after upgrade from 4.0 to 4.1 ("This class does not inherit from Node") and got this error. I just changed it to Node3D and back, and then the "cache" bug got fixed magicly?

System.Text.Json also has this issue where serializing your classes will be held internally by the Json library.

The workaround for this using this library is also copied below:

var assembly = typeof(JsonSerializerOptions).Assembly;
var updateHandlerType = assembly.GetType("System.Text.Json.JsonSerializerOptionsUpdateHandler");
var clearCacheMethod = updateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public);
clearCacheMethod?.Invoke(null, new object?[] { null }); 

As far as I'm aware Godot doesn't provide an event for signalling when your dll/plugin is about to be unloaded, so you essentially need to call the above solution after every serialization/deserialization.

As far as I'm aware Godot doesn't provide an event for signalling when your dll/plugin is about to be unloaded, so you essentially need to call the above solution after every serialization/deserialization.

You can use the normal AssemblyLoadContext.Unloading event to trigger such cleanup code. I unfolded the code example in the initial post demonstrating its usage.

You can use the normal AssemblyLoadContext.Unloading event to trigger such cleanup code. I unfolded the code example in the initial post demonstrating its usage.

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:

internal class AppModule
{
    [System.Runtime.CompilerServices.ModuleInitializer]
    public static void Initialize()
    {
        System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(System.Reflection.Assembly.GetExecutingAssembly()).Unloading += alc =>
        {
            var assembly = typeof(JsonSerializerOptions).Assembly;
            var updateHandlerType = assembly.GetType("System.Text.Json.JsonSerializerOptionsUpdateHandler");
            var clearCacheMethod = updateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public);
            clearCacheMethod?.Invoke(null, new object?[] { null });

            // Unload any other unloadable references
        };
    }
}

This ensures it is not dependent on any node(s) and is always registered only once, and re-registered upon reloading the assembly.

I am not using Json.NET or System.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 to default.

The only library I am referencing is one I have authored. My .csproj file looks like this:

<Project Sdk="Godot.NET.Sdk/4.1.0">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <EnableDynamicLoading>true</EnableDynamicLoading>
  </PropertyGroup>
  <ItemGroup>
    <ProjectReference Include="..\Lib\Hawthorn\Hawthorn\Hawthorn.csproj" />
  </ItemGroup>
</Project>

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.

It refers to Microsoft's docs page that was linked a bit further up: https://learn.microsoft.com/en-us/dotnet/standard/assembly/unloadability#troubleshoot-unloadability-issues

Also all these really also have to apply to the library, but for most libraries there isn't too much you can do about it (except not use the library)

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:

modules/mono/glue/runtime_interop.cpp:1324 - System.ArgumentException: An item with the same key has already been added. Key: BehaviorActorView`1[LeshonkiView]
     at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
     at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
     at Godot.Bridge.ScriptManagerBridge.ScriptTypeBiMap.Add(IntPtr scriptPtr, Type scriptType) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs:line 23
     at Godot.Bridge.ScriptManagerBridge.TryReloadRegisteredScriptWithClass(IntPtr scriptPtr) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs:line 579

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.

You also seem to be using generic Nodes which also cause issues in some cases, see #79007

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.

I have created that reproduction project: #79519

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.

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.

I can absolutely understand that. The problems since 4.1 are unfortunately unexpected, varied and sometimes difficult to analyse. The new GlobalClass attribute does not work correctly for me so far, so I will not use this great feature for the time being. But I still got the error message above.

As described above, some problems are related to tool code whose assemblies cannot be unloaded during build. This certainly has side effects on GlobalClass classes. In principle, this is a problem of .net and poorly implemented libs (which cannot be unloaded) and not an engine bug. But it is important that a solution is found, because it makes the use of .net, especially as tool-code in the editor, much more difficult.

The simplest workaround is probably to close the problematic scene tabs (mostly [tool] code) before each build. Of course, this is annoying and tedious.

Otherwise, try the code listed at the top. Surprisingly, the following worked for me:

`[Tool]
...
            AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly()).Unloading += alc =>
            {

               // trigger unload 
                AssemblyLoadContext.GetLoadContext(typeof(JsonSerializerOptions).Assembly).Unload();
                AssemblyLoadContext.GetLoadContext(typeof(DataContractJsonSerializer).Assembly).Unload();

                // Unload any other unloadable references					

            };   

With this code, the unload works after an incorrect attempt.

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.

I added generic nodes today, and I started getting this issue.

I'm getting this issue in 4.1, and I'm not using any third-party libraries, nor am I using generic nodes, nor am I using the [GlobalClass] or [Tool] attributes. It just seems to be happening at random whenever I recompile.

Well, OK. I used to have a C# script that had both of those attributes, but I've since rewritten it in GDScript, so it shouldn't be relevant anymore...right? Is there any chance that the ghost of the C# version of that script still lives on? Maybe in some cache somewhere?

Also happens whenever I enable a C# editor plugin, and only goes away once I disable the plugin and restart the editor.

The new [GlobalClass] attribute also causes this problem because these classes make it act like [Tool] code. The basic problem probably lies in the System.Collection.Generic class. :

  modules/mono/glue/runtime_interop.cpp:1324 - System.ArgumentException: An item with the same key has already been added. Key: Game.WeaponAbilityData
     at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
     at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
     at Godot.Bridge.ScriptManagerBridge.ScriptTypeBiMap.Add(IntPtr scriptPtr, Type scriptType) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs:line 23
     at Godot.Bridge.ScriptManagerBridge.AddScriptBridge(IntPtr scriptPtr, godot_string* scriptPath) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs:line 419

I will try today the method mentioned above by Quinn-L and put the unload handler in an EditorPlugin. But I have rather little hope that it will work cleanly.

I will try today the method mentioned above by Quinn-L and put the unload handler in an EditorPlugin. But I have rather little hope that it will work cleanly.

Nope. We decided not to waste so much time with this problem and rewrite certain parts of the code in GDScript to work around the trouble spots with C#. We are not happy with this. This will especially affect [GlobalClass] and [Tool] code, probably also System.Collection.Generic will cause trouble.

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.

namespace FlightSpeedway
{
    public partial class Player : CharacterBody3D
    {
        private PlayerState _currentState;
        private Vector3 _spawnPoint;
        private Vector3 _spawnRotation;

        public void ChangeState<TState>() where TState : PlayerState
        {
            GD.Print($"Changing state to {typeof(TState).Name}");
            _currentState?.OnStateExited();

            foreach (var state in States())
            {
                state.ProcessMode = ProcessModeEnum.Disabled;
            }

            _currentState = States().First(s => s is TState);
            _currentState.ProcessMode = ProcessModeEnum.Inherit;
            _currentState.OnStateEntered();
        }

        private IEnumerable<PlayerState> States()
        {
            for (int i = 0; i < GetChildCount(); i++)
            {
                var child = GetChild<Node>(i);

                if (child is PlayerState state)
                    yield return state;
            }
        }
    }

    public partial class PlayerState : Node
    {
        protected Player _player => GetParent<Player>();
        protected Node3D _model => GetNode<Node3D>("%Model");

        public virtual void OnStateEntered() {}
        public virtual void OnStateExited() {}
    }
}

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 inherit PlayerState. Those nodes exist as children of the player node, and they get enabled/disabled as the player changes states.

I will try today the method mentioned above by Quinn-L and put the unload handler in an EditorPlugin. But I have rather little hope that it will work cleanly.

Nope. We decided not to waste so much time with this problem and rewrite certain parts of the code in GDScript to work around the trouble spots with C#. We are not happy with this. This will especially affect [GlobalClass] and [Tool] code, probably also System.Collection.Generic will cause trouble.

System.Collections.Generic definitely does not cause trouble. I've been using it extensively in a different Godot 4.1 project, and have never seen this problem in that project.

No, it's because I had more than one Node class in a single script file.

I can't confirm, we have all classes in separate files and as soon as [Tool] or [GlobalClass] is used, there are the problems described above. With [Tool] code you can work around the problem by closing these scene tabs before compiling. With [GlobalClass] you can't, because the editor keeps instances of these classes persistently in the background and the binding of some libs prevents unloading. And as I see it, System.Collection.Generic is used by the Godot code generator and this might cause trouble, because maybe one of the libraries in this namespace can't be unloaded correctly. I.e. even if you don't use a Generic in your [GlobalClass] script, it causes problems in the editor. At least this is always the case with us.

No, it's because I had more than one Node class in a single script file.

I can't confirm, we have all classes in separate files and as soon as [Tool] or [GlobalClass] is used, there are the problems described above.

I'm not saying those scripts don't trigger the problem; I'm saying that multiple nodes in one file also triggers this problem.

There are multiple causes of this problem. From the comments, there are at least three ways you can run into the issue..

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?

Rylius commented

Just ran into this issue but in a seemingly different way than described above.

Failing code:

[GlobalClass]
public partial class WeaponDefinition : Resource
{
    [Export]
    public InventoryItemDefinition InventoryItem { get; private set; } = new();
}

InventoryItemDefinition is another GlobalClass resource. Figured I'd initialize the property with new() but that is a really bad idea. Think this causes some issues in the resource editor too, in addition to this issue.

Fixed code:

[GlobalClass]
public partial class WeaponDefinition : Resource
{
    [Export]
    public InventoryItemDefinition InventoryItem { get; private set; } = null!;
}

Just ran into this issue but in a seemingly different way than described above.

Failing code:

[GlobalClass]
public partial class WeaponDefinition : Resource
{
    [Export]
    public InventoryItemDefinition InventoryItem { get; private set; } = new();
}

InventoryItemDefinition is another GlobalClass resource. Figured I'd initialize the property with new() but that is a really bad idea. Think this causes some issues in the resource editor too, in addition to this issue.

Fixed code:

[GlobalClass]
public partial class WeaponDefinition : Resource
{
    [Export]
    public InventoryItemDefinition InventoryItem { get; private set; } = null!;
}

Are you sure it was new() that was the problem, and not the fact that it was being initialized in the first place? If you actually assign it a value in the inspector, does the problem come back?

Rylius commented

Are you sure it was new() that was the problem, and not the fact that it was being initialized in the first place? If you actually assign it a value in the inspector, does the problem come back?

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.
With null! the inspector just shows "<empty>" (as expected), and assigning a new resource or loading an existing saved one work perfectly fine.

Interesting! Have you tried what happens when you change the GlobalClass code and run the build again? This leads to the known problems with us, because the GlobalClass assemblies (like [Tool] also) run in the editor and have to be unloaded for the new version, but this often fails.

Rylius commented

My project currently has 21 classes with [GlobalClass] (mostly resources, some nodes) and so far I haven't had any issues when it comes to unloading. Adding new [Export] properties and modifying methods both work fine.
(I don't have any [Tool] classes, addons or editor plugins, if that helps?)

Huge thanks @Rylius!
I was in the exact same case where I used to initialize my exported properties like this:

[Export]
public MyCustomResource MyProperty { get; set; } = new() { ResourceLocalToScene = true };

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.

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).

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.

Hi! I've encountered this issue by manually subscribing to UI control actions, such as Button.Pressed in _EnterTree, something like

[Tool]
public partial class Test : Control
{
	[Export]
	private Button _button;
	public override void _EnterTree()
	{
		_button.Pressed += OnButtonPressed;
	}

	private void OnButtonPressed()
	{

	}
}

I've worked around this by setting up signals inside Godot Editor, although I don't really like this pattern and would prefer to subscribe/unsubscribe through code.

Just to add to the list of possible causes: I used the dynamic keyword when implementing a generic class. This created a closure that was never garbage collected, and caused assembly unloading to fail. I don't know enough about how the dynamic keyword is implemented, but I want to put it out there as a potential cause for some people.

Just got the same issue when trying to implement a simple C# plugin that adds a button to the inspector for any method annotated with a custom attribute, like so:

public partial class InspectorButtonPlugin : EditorInspectorPlugin
{
    public override bool _CanHandle(GodotObject @object)
    {
        if (@object is not Node node) return false;
        var methods = node.GetType().GetMethods();
        return methods.Any(
            method => method.GetCustomAttribute<InspectorButtonAttribute>() != null
        );
    }

    public override void _ParseBegin(GodotObject @object)
    {
        if (@object is not Node node) return;

        var methods = node.GetType().GetMethods();

        foreach (var method in methods)
        {
            var attribute = method.GetCustomAttribute<InspectorButtonAttribute>();
            if (attribute == null) continue;

            var button = new Button();
            button.Text = attribute.Name ?? method.Name;
            button.Pressed += () => method.Invoke(@object, null);  // <<<< causes unload issues
            // button.Connect("pressed", new Callable(node, method.Name)); // <<<< works fine

            AddCustomControl(button);
        }
    }
}

The workaround only seems to work if the method doesn't return anything tough, otherwise it complains with Error calling from signal 'pressed' to callable: (...) Method not found

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?

Is there a reason why no attached console could cause this?

This is interesting. I just realized that if you open Godot via console, then close it (by clicking the window close button X), the console still shows a cursor as if Godot was still running. So maybe when you re-open Godot there's still background Godot processes running and holding a lock to the .NET assemblies. 🤔

[Edit] I also get the following error when

  1. Open Godot mono
  2. Load a project
  3. Run the project
  4. Stop running the project
  5. Close Godot
Godot Engine v4.1.2.stable.mono.official.399c9dc39 - https://godotengine.org
Vulkan API 1.3.242 - Forward+ - Using Vulkan Device #0: NVIDIA - NVIDIA GeForce RTX 3080

ERROR: Condition "!EditorSettings::get_singleton() || !EditorSettings::get_singleton()->has_setting(p_setting)" is true. Returning: Variant()

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

@RedworkDE Could you maybe edit #81903 into the initial post? It seems to be a reliable way to trigger this issue.

I closed Godot and opened it in Admin mode. Error fixed to me.

For anyone who ends up here and is now desperate about not being able to use the Json.Net and System.Text.Json mentioned in the initial post, I migrated all of my JSON code to use the libs below and they are working just fine

https://github.com/Bunny83/SimpleJSON - For generic JSON manipulation, building and reading JSONObjects manually through your own code
https://github.com/zanders3/json - From Serialization and deserialization. Works with custom classes, so you can parse or write them pretty easily

There might be better solutions out there, but for me these two simple scripts worked perfectly

I hope this helps someone!

There might be better solutions out there, but for me these two simple scripts worked perfectly

Newtonsoft is a better solution, it's what I use. Installing it is very easy as well.

Edit: This does not solve the unloading issue but may allow the DotNet module to self-recover (instead of restarting the editor) in case of a failed unloading.

Correct me if I am wrong, I only have a basic understanding of the GodotSharp structure.

Just saw one of Unity's solutions for addressing the ALC unloading issue as they are designing the new Editor which runs on Modern DotNet, wondering if their solution is applicable to solving our issue as well.
Here is the link to the original Unity forum:
Unity Future .NET Development Status

Here is a quote from their solution:

How will we use ALCs?
We will have the following ALC structure (note: it is still subject to change)

  • Unity.Loader + CoreCLR PrivateCoreLib in the default ALC (which is not unloadable) - Layer 0
  • Unity Modules (except platform-specific modules) + .net BCL libraries in a first unloadable ALC - Layer 1
  • White listed packages are known to auto-clean their events and static fields + platform-specific modules - Layer 2
  • User code + non-white listed packages - Layer 3

How will we prevent leaking ALC from the Unity API (Unity modules) ?

  • We are in the process of cleaning up our API replacing all static fields by properties
  • We are working on roslyn source generators helping us to intercept all potentially problematic static properties and events assignments, identifying the layer of the referenced object and register it of auto-cleanup on ALC unload
  • If that fails and we detect ALC leaks, we will have an heuristic that will make the next code reload unload both layer 3 and 2, then if it still fails, will unload all 3 layers.

From my understanding, if there is a way we can ensure the GodotSharpEditor itself is ALC compatible (and load that to the editor by ALC, let's say Layer 1), it is possible for us to just "Nuke" the entire GodotSharpEditor (Layer 1) and User Code / User Plugin Code (Layer 2/ 3) and reload them incase a User Code level reload fails.

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:

[Export]
public ItemStats Stats = new ItemStats();

The fix as @Rylius said is as follows:

[Export]
public ItemStats Stats = null;

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!

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
{

	[Export]
	public OptionButton gameReSolution{get;set;}
	public Resolution gameReSolutionData{get;set;}  

      .....................

& --------------------------------------
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.

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 {

	[Export]
	public OptionButton gameReSolution{get;set;}
	public Resolution gameReSolutionData{get;set;}  

      .....................

& -------------------------------------- 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.

If possible, can you share a minimal reproduction project of your case?

Not exactly a library that causes this issue, but relevant for troubleshooting: Check Visual Studio extensions too?

I ran into this error message after working on a custom source generator for my project. After disabling an extension called "Source Generator Auto Update", everything worked fine.

The trick of starting the editor in admin mode actually worked for me up to V 4.1.x. From version 4.2.x, however, it no longer works. Tool and GlobalClass scripts cause problems.

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:

Object(Container,"_import_path":NodePath(""),"unique_name_in_owner":true,"process_mode":0,"process_priority":0,"process_physics_priority":0,"process_thread_group":0,"editor_description":"","visible":true,"modulate":Color(1, 1, 1, 1),"self_modulate":Color(1, 1, 1, 1),"show_behind_parent":false,"top_level":false,"clip_children":0,"light_mask":1,"visibility_layer":1,"z_index":0,"z_as_relative":true,"y_sort_enabled":false,"texture_filter":0,"texture_repeat":0,"material":null,"use_parent_material":false,"clip_contents":false,"custom_minimum_size":Vector2(499, 373),"layout_direction":0,"layout_mode":2,"size_flags_horizontal":4,"size_flags_vertical":4,"size_flags_stretch_ratio":1.0,"auto_translate":true,"localize_numeral_system":true,"tooltip_text":"","focus_neighbor_left":NodePath(""),"focus_neighbor_top":NodePath(""),"focus_neighbor_right":NodePath(""),"focus_neighbor_bottom":NodePath(""),"focus_next":NodePath(""),"focus_previous":NodePath(""),"focus_mode":0,"mouse_filter":1,"mouse_force_pass_scroll_events":true,"mouse_default_cursor_shape":0,"shortcut_context":null,"theme":null,"theme_type_variation":&"","script":Resource("res://Scenes/Arena/Battlefield/Grid.cs"),"GridSize":Vector2i(8, 6),"SlotSize":58.0,"SlotSpacing":5.0,"IsOnPlayerGrid":true,"Slot":Resource("res://Scenes/Arena/Battlefield/GridSlot.tscn"),"gridSize":Vector2i(8, 6),"slotSize":58.0,"slotSpacing":5.0,"isOnPlayerGrid":true,"slot":Resource("res://Scenes/Arena/Battlefield/GridSlot.tscn"))

I mostly report this error for search result purpose.
If I have time, I will try to make a repro project.

My currently open scene will be resaved with weird or null value in the field.

Feels related to #85492

My currently open scene will be resaved with weird or null value in the field.

Feels related to #85492

Unfortunately, this happens when the values of [export] properties (for open scenes) have been damaged by the bug (without them realizing it) and then another build is executed. Godot then writes the corrupted values into the scenes or loses the binding.

My currently open scene will be resaved with weird or null value in the field.

Feels related to #85492

Unfortunately, this happens when the values of [export] properties (for open scenes) have been damaged by the bug (without them realizing it) and then another build is executed. Godot then writes the corrupted values into the scenes or loses the binding.

Yes, hence me linking the other issue.

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?

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?

FWIW, I was struggling with these exact issues but managed to fix it by altering parts of my code to fit some of the suggestions in this issue - the ones in particular that got me a few times were mentioned in this response: #78513 (comment) (initialising exported properties), as well as this one a few times: #78513 (comment) (subscribing to events in [Tool] when executing in the editor).

Since removing things like that from my code I've not encountered this issue.

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?

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

Wow, that is a rabbit hole. So far though it seems to be working, thank you so much for that!

I'm pretty sure the answer on this is going to be no, but is there a way for me to check in my code that the patched version of that DLL is being used? To like kick up an error or something if one of my teammates forgets to apply it?

Wow, that is a rabbit hole. So far though it seems to be working, thank you so much for that!

I'm pretty sure the answer on this is going to be no, but is there a way for me to check in my code that the patched version of that DLL is being used? To like kick up an error or something if one of my teammates forgets to apply it?

@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.

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

I'm getting "Unable to load .NET runtime, no compatible version was found."-issues with this build. I have installs of the .NET SDK 6, 7 and 8 on my computer (Running Windows 10). Unsure if it's an issue with this specific build or if it's related to the fix, or if the error lies between chair and keyboard.

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

I'm getting "Unable to load .NET runtime, no compatible version was found."-issues with this build. I have installs of the .NET SDK 6, 7 and 8 on my computer (Running Windows 10). Unsure if it's an issue with this specific build or if it's related to the fix, or if the error lies between chair and keyboard.

That's weird, how about having a try on the current main branch? I believe the Generic Entries-related issue has been fixed as #87550 (which fixes the underlying issue without touching any CSharp scripts) has merged.

I get the Godot.Bridge.ScriptManagerBridge.TryReloadRegisteredScriptWithClass error for 3 classes in my project.

given:

public abstract partial class AbstractMainNode : Node2D {}
public interface IUIStackComponent {}

The following classes cause the problem

public partial class MainNode : AbstractMainNode {}
public partial class UIStackControl : Control, IUIStackComponent {}
public partial class UIStackGridContainer : GridContainer, IUIStackComponent {}

I got no generics, the code should easily figure out the final type of the script.

I have to say this has been pretty frustrating, I've been wasting more time fighting with the engine than actually building my game.

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.

Started getting this error out of nowhere after renaming a class through Visual Studio (using F2) instead of the Editor. Because of this, there was a class in my project with a different name than the name of it's file, and apparently Godot does not like this. I renamed the file to match the new name of the class through the Editor, and the error stopped after restarting the Editor.

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:

Thank you, this was maddening, and fixed my issue!

I get the Godot.Bridge.ScriptManagerBridge.TryReloadRegisteredScriptWithClass error for 3 classes in my project.

given:

public abstract partial class AbstractMainNode : Node2D {}
public interface IUIStackComponent {}

The following classes cause the problem

public partial class MainNode : AbstractMainNode {}
public partial class UIStackControl : Control, IUIStackComponent {}
public partial class UIStackGridContainer : GridContainer, IUIStackComponent {}

I got no generics, the code should easily figure out the final type of the script.

I have to say this has been pretty frustrating, I've been wasting more time fighting with the engine than actually building my game.

@sebialex I think based on what I'm reading here, node inheritance is simply a no-no in godot C#. So you can't do the AbstractMainNode thing. So far I think the options are (a) use composition instead of inheritance, (b) do all your inheritance completely outside of godot and keep adding interfaces like you're doing. So far I'm going with a mix of those two and its kind of working ok; but still not a great experience.

From my experience, if you inherit a type (like a custom Node) from another assembly, then you will start having this issue as well.

@Ryan-000 I think that's what might be the issue for me, the AbstractMainNode is in another assembly.

The recent 4.3 dev 3 update did help though.

There are quite a few possible issues causing assemblies to fail to unload.

Some are out of our control.

  • Other libraries aren't friendly to being unloaded (cf. original message).
  • Your game code is not friendly to being unloaded. It is less common, but still possible.
  • In both cases, some features like dynamic are known to be basically incompatible with assembly unloading.

Some are bugs in Godot. As of now, the following have been identified.

  • Fix is currently in 4.3.dev
  • Fix is to be merged, but waiting
    • #81903 (edit on April 5th: this is now also merged)

I'll edit if I remember other linked issues.

With regards to your bullet points, are there any C# guidelines for Tool development that outline a pattern for ensuring it's not our code that's causing the issue?

Not really, apart from checking it doesn't fall under #81903, and referring you to the guidelines linked in the original post. Keep in mind, it could also be a cause nobody has identified yet.

I'm still seeing this issue in 4.3 dev-3.

In fact, I have not yet managed to reproduce the problem in 4.3 dev-3. Everything worked as expected and without the typical problems. That actually made me feel positive. However, I have only tested with a few very simple scripts [GlobalClass], [Tool] and System.Collection.Generic.

Probably yes, because the C# script must also be tool code in order to be able to access its properties from GDScript.

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 :/

Can anyone confirm any of the existing reproduction methods still trigger this?

AFAIK all the obvious cases we have highlighted until now should be fixed now.

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.

Been iterating on my game quite a bit since yesterday, after building the latest with all of the fixes, and got another unload assembly crash in editor today.

It is giving me a lot of logs pointing back to NativeUtils, DelegateUtils and GodotObject. Unload_Assembly_Crash_v4.3.dev.mono.custom_build [febb11f8a].txt

The referenced "RadialPatternResolver" is a Tool script that contains a reference to a GlobalClass Resource.

If possible, can you publish an issue about this, and, include a MRP (minimal reproducible project) for this issue you are encountering?

its early thats why is not publicly promoted https://github.com/raulsntos/godot-dotnet

its huge initial commit because it was worked on for months in private
if by migrated you mean in godot, its going to be like godot-cpp not in godot i think

its early thats why is not publicly promoted https://github.com/raulsntos/godot-dotnet

Is this new work or copying over what exists now for refactoring? It looks like a huge initial commit of 389 files was added last week.

If the new project is a refactor, it would be great to know how these fixes will be migrated.

In addition, this repo is in a very early stage, so it's not recommended to start your project on it.

Is there a flow chart or design diagram for how any of the current C# implementation works? Juan says there is a new .NET implementation coming but there is no ETA. I wouldn't mind potentially digging into this if someone with some knowledge on it wants to help. I don't have time to reverse engineer it.

In the interim, I'm bypassing the EmitChange call in the custom resources and have hooked up a normal C# event instead. Going to run more testing to see if I hit the issue with this change. If not, we can at least assume the native callback implementation is a good place to start poking around.

I would not choose to do anything complex in an [Export]ed property personally, shenanigans could happen when you talking to the native side (any method call other than EmitChanged() that invokes the native side) in the middle of property deserialization.

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.

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!

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!

This issue has fixed in 4.3 you may try it out if the fix works.
#83217

It's not in 4.3.dev5, it will be in dev6 which should release in a few days

It's not in 4.3.dev5, it will be in dev6 which should release in a few days

I compiled the latest godot from the master branch, but I still encounter this problem. I can only solve it by binding the event this way: xxxx.Connect(SignalName.Pressed, new Callable(this, MethodName.XXXX)

  1. Do not use += to bind events
  2. Do not use anonymous functions

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?

It's not in 4.3.dev5, it will be in dev6 which should release in a few days

I compiled the latest godot from the master branch, but I still encounter this problem. I can only solve it by binding the event this way: xxxx.Connect(SignalName.Pressed, new Callable(this, MethodName.XXXX)

  1. Do not use += to bind events
  2. Do not use anonymous functions

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?

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:

using Godot;

[Tool]
public partial class Main : GridContainer
{
        public override void _Ready()
        {

                for (int i = 0; i < 9; ++i)
                {
                        Button button = new()
                        {
                                Text = i.ToString(),
                        };

                        int id = i;
                        button.Pressed += () =>
                        {
                                OnButtonPressed(id);
                        };

                        AddChild(button);
                }
        }

        private void OnButtonPressed(int id)
        {
                GD.Print($"Button {id}");
        }
}

My testing process is:

  1. Start godot and open the main scene, making sure that the editor renders the content of the scene.
  2. Start vscode, modify a little bit of code, and click the run button in godot editor to compile and run the code.

It's not in 4.3.dev5, it will be in dev6 which should release in a few days

I compiled the latest godot from the master branch, but I still encounter this problem. I can only solve it by binding the event this way: xxxx.Connect(SignalName.Pressed, new Callable(this, MethodName.XXXX)

  1. Do not use += to bind events
  2. Do not use anonymous functions

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?

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:

using Godot;

[Tool]
public partial class Main : GridContainer
{
        public override void _Ready()
        {

                for (int i = 0; i < 9; ++i)
                {
                        Button button = new()
                        {
                                Text = i.ToString(),
                        };

                        int id = i;
                        button.Pressed += () =>
                        {
                                OnButtonPressed(id);
                        };

                        AddChild(button);
                }
        }

        private void OnButtonPressed(int id)
        {
                GD.Print($"Button {id}");
        }
}

My testing process is:

  1. Start godot and open the main scene, making sure that the editor renders the content of the scene.
  2. Start vscode, modify a little bit of code, and click the run button in godot editor to compile and run the code.

See the .Net specific page for Compiling the Engine.

It's not in 4.3.dev5, it will be in dev6 which should release in a few days

I compiled the latest godot from the master branch, but I still encounter this problem. I can only solve it by binding the event this way: xxxx.Connect(SignalName.Pressed, new Callable(this, MethodName.XXXX)

  1. Do not use += to bind events
  2. Do not use anonymous functions

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?

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:

using Godot;

[Tool]
public partial class Main : GridContainer
{
        public override void _Ready()
        {

                for (int i = 0; i < 9; ++i)
                {
                        Button button = new()
                        {
                                Text = i.ToString(),
                        };

                        int id = i;
                        button.Pressed += () =>
                        {
                                OnButtonPressed(id);
                        };

                        AddChild(button);
                }
        }

        private void OnButtonPressed(int id)
        {
                GD.Print($"Button {id}");
        }
}

My testing process is:

  1. Start godot and open the main scene, making sure that the editor renders the content of the scene.
  2. Start vscode, modify a little bit of code, and click the run button in godot editor to compile and run the code.

See the .Net specific page for Compiling the Engine.

Thank you! I can confirm that the new version has indeed fixed this issue.

I encountered this error regularly in 4.2.2 as well. Running Godot Engine v4.3.dev.mono.custom_build.7529c0bec I no longer encounter the issue on any normal script, but I have a editor plugin that fails almost instantly as I run the project

As stated in the original message: if you're encountering this error, think the issue is caused by Godot, and does not fall in the list of already reported causes (the list up top is edited and maintained up to date), please open a dedicated issue. Thank you.

Hello, I encountered the issue by adding a static constructor on a node class (used to initialize a static variable to avoid having to declare it as a nullable). I initialized it in the node constructor and ignored the warning CS8618 as a workaround.

@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?

Hello, I received the same error message in version 4.2.2. When changing an EditorPlugin written in C#. More precisely, when a script was attached to the [Tool] attribute to use it in the EditorPlugin.

Godot Engine v4.2.2.stable.mono.official (c) 2007-present Juan Linietsky, Ariel Manzur & Godot Contributors.

modules/mono/mono_gd/gd_mono.cpp:529 - .NET: Failed to unload assemblies. Please check https://github.com/godotengine/godot/issues/78513 for more information. (User)
modules/mono/mono_gd/gd_mono.cpp:529 - .NET: Failed to unload assemblies. Please check https://github.com/godotengine/godot/issues/78513 for more information. (User)
modules/mono/mono_gd/gd_mono.cpp:529 - .NET: Failed to unload assemblies. Please check https://github.com/godotengine/godot/issues/78513 for more information. (User)
modules/mono/mono_gd/gd_mono.cpp:513 - .NET: Giving up on assembly reloading. Please restart the editor if unloading was failing. (User)

Good idea to write this in an error message.

I thought I was done with these kind of issues (4.3.dev6 looked like it was good), but I'm getting this after upgrading to 4.3.beta1 (Windows 10, .NET).

 Assertion failed: Script path can't be empty.
    Details: 
     at Godot.GodotTraceListener.Fail(String message, String detailMessage) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/GodotTraceListener.cs:line 24
     at System.Diagnostics.TraceInternal.Fail(String message, String detailMessage)
     at System.Diagnostics.Debug.Fail(String message, String detailMessage)
     at Godot.Bridge.ScriptManagerBridge.GetGlobalClassName(godot_string* scriptPath, godot_string* outBaseType, godot_string* outIconPath, godot_string* outClassName) in /root/godot/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs:line 232

No idea which of my source files is causing this, it doesn't say. I'm not sure if this is related, but it feels like it.

Hello, I received the same error message in version 4.2.2. When changing an EditorPlugin written in C#. More precisely, when a script was attached to the [Tool] attribute to use it in the EditorPlugin.

Godot Engine v4.2.2.stable.mono.official (c) 2007-present Juan Linietsky, Ariel Manzur & Godot Contributors.

modules/mono/mono_gd/gd_mono.cpp:529 - .NET: Failed to unload assemblies. Please check https://github.com/godotengine/godot/issues/78513 for more information. (User)
modules/mono/mono_gd/gd_mono.cpp:529 - .NET: Failed to unload assemblies. Please check https://github.com/godotengine/godot/issues/78513 for more information. (User)
modules/mono/mono_gd/gd_mono.cpp:529 - .NET: Failed to unload assemblies. Please check https://github.com/godotengine/godot/issues/78513 for more information. (User)
modules/mono/mono_gd/gd_mono.cpp:513 - .NET: Giving up on assembly reloading. Please restart the editor if unloading was failing. (User)

Good idea to write this in an error message.

#78513 (comment)
#78513 (comment)
https://learn.microsoft.com/en-us/dotnet/standard/assembly/unloadability#troubleshoot-unloadability-issues

Does anyone of those links explain the behaviour that the assembly unload stops working after a couple of reloads? I'm still on 4.2.2 but that's what I'm seeing: assembly reloading works a couple of times usually after which it stops working. I don't think any new code from my side that uses any of the things that are said to cause assembly unloading issues would run only after like the seconds or third time an assembly reload happens.

Does anyone of those links explain the behaviour that the assembly unload stops working after a couple of reloads? I'm still on 4.2.2 but that's what I'm seeing: assembly reloading works a couple of times usually after which it stops working. I don't think any new code from my side that uses any of the things that are said to cause assembly unloading issues would run only after like the seconds or third time an assembly reload happens.

4.2.x is suffering from all four major issues. These are bugs within the Godot Engine / .Net Module that a user will encounter regardless of whether they are creating Editor Tools or not. These issues are fixed in 4.3 but not (yet?) cherry-picked to 4.2 (or maybe never for #81903 because of this).
#79519
#81903
#80175
#90837
But things are different for EditorPlugins. Failed unloading can happen by user error, especially during editor script development where exceptions can break unloading functionalities, or as the link explains, certain libraries or use cases are not unloadable by C# design, there is nothing for us language consumer can do other than rebooting the editor.

I encounter this after compiling/running scene with another godot instance, mostly from command line after compiling new csharp scripts (IDE: Jetbrains Rider).

godot --path ".../my project path" "res://Scenes/GameMain.tscn"

And then I go back to the editor, it pops up this thread.

I would like to share my Theory.

TL;DR; Multiple Resource classes that are "GlobalClass" and located in the same file are problematic and when you refactor all your resource into separated files, this issue disappear.

The long version:

I was having this issues through 4.2 until 4.3-RC1. Just before RC1 release, I had refactor a lot of my code and split files from multiple classes inside a single file to each class has it's own separated file. When RC1 release, I just finished that refactor and I was happy that the Engine was now working. I've though the issue was solve within RC1, while it wasn't mention though the changelog.

RC1, RC2, RC3 and 4.3-stable were all improving my experience until I've start designing a new systems for my game. This issues that was uncleared to me but only allowed me to build my project once per "Godot execution" was back and worst. Then I though maybe I have found the culprit.

Right now I can't confirm but I highly think I've found a reproductible pattern. When I had the issue, I had multiple Resource classes found in the same file at multiple location.

I had this issues where my scenes where corrupted after running into this issues and saving my scene. (AKA: Running your game will save any opened and edited scene which were edited not by me, but by the compilation issue process. Resulting that after any build that has failed, the following build will corrupt your opened scene if this issues has happen. the C# meta data is corrupted and Godot will try using this new meta data, will find any node with a "Resource" [Export] property to be incorrect and will corrupt it with a null value...). All my tscn files changed and now having exported variable inserted to null instead of what it was before.

Signal were corrupted and to have my build working again, I had to "reset" each exported variable that was corrupted. I've start connecting signals through my C# code due to that issues...

But one of the things I notice is that all my "resource" exported variable where the Script value in the Inspector was "corrupted". (By memory) It look like: "res://src/SomethingComponent.cs::Resource_4go2v" the UUID at the end. I had to manually connect the Script to the Right C# file to fix the issues and it was reccuring like "Moe's kicking Barney out of his bar" meme.

One thing I made sure to fix in the refactoring I have done prior to RC1 was that I had one file with like 10 Resource "GlobalClass" and one day I've decide to refactor all those classes into separated file for each Resource class. After fixing my .tres files, it didn't happen for like 3 weeks. Until I start working on my next systems, which I guess I start creating new Resource classes and put multiple resource classes inside the same file again. Now I am stuck with this issues which disappear for a short period.

Pretty sure it's related to something like this. When I will tackle the refactoring, I will make sure to do a follow up about this theory. Until then, I encourage anybody to test this solution if it solved the issue. At least, if it doesn't solve the issues, it will reduced the Tech Debt in their game. Lol

Those are example of visual distinction found when the bug happen.

image
image

I don't think I've used any Godot resources at all. Other than the built-in ones of course. So I think my project contains zero resources with a C# script related to them. And I still see this issue (though I haven't updated to 4.3 yet as I've been busy the past week) so I don't think that can be the whole picture.

Edit: I've now tried Godot 4.3 and I still got the same issue within about 5 minutes.

Is it possible that the resourceformatsaver and resourceformatloader that you wrote yourself could cause this problem?