godot: Can't get method on CallableCustom "Delegate::Invoke" error when building/debugging .NET project

Godot version

4.0beta

System information

windows10,NVIDIA GeForce GTX 1660,Vulkan API 1.2.0

Issue description

GODOT BETA 7.0 C # version, when debugging for many times, suddenly stuck, the debugging progress bar did not respond, and then if the program was not forced to close in time, the entire operating system would crash. But there is no error prompt, After I restart the computer, a lot of errors will occur when I open the project:

  modules/mono/managed_callable.cpp:92 - Condition "delegate_handle.value == nullptr" is true.
  Can't get method on CallableCustom "Delegate::Invoke".
  core/object/object.cpp:1058 - Error calling from signal 'timeout' to callable: 'Node::': Method not found.
  modules/mono/managed_callable.cpp:92 - Condition "delegate_handle.value == nullptr" is true.
  Can't get method on CallableCustom "Delegate::Invoke".
  core/object/object.cpp:1058 - Error calling from signal 'timeout' to callable: 'Node::': Method not found.
  modules/mono/managed_callable.cpp:92 - Condition "delegate_handle.value == nullptr" is true.
  Can't get method on CallableCustom "Delegate::Invoke".
  core/object/object.cpp:1058 - Error calling from signal 'timeout' to callable: 'Node::': Method not found.
  modules/mono/managed_callable.cpp:92 - Condition "delegate_handle.value == nullptr" is true.
  Can't get method on CallableCustom "Delegate::Invoke".
  core/object/object.cpp:1058 - Error calling from signal 'timeout' to callable: 'Node::': Method not found.
  modules/mono/managed_callable.cpp:92 - Condition "delegate_handle.value == nullptr" is true.
  Can't get method on CallableCustom "Delegate::Invoke".
  core/object/object.cpp:1058 - Error calling from signal 'timeout' to callable: 'Node::': Method not found.
  modules/mono/managed_callable.cpp:92 - Condition "delegate_handle.value == nullptr" is true.
  Can't get method on CallableCustom "Delegate::Invoke".
  core/object/object.cpp:1058 - Error calling from signal 'timeout' to callable: 'Node::': Method not found.
  modules/mono/managed_callable.cpp:92 - Condition "delegate_handle.value == nullptr" is true.

Deleting the godot folder can solve the problem, but it will seriously affect my computer health and my spirit. I’m going crazy. Please solve this problem, otherwise it will become difficult to use, thank you.

Steps to reproduce

N/A

Minimal reproduction project

N/A

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 8
  • Comments: 32 (6 by maintainers)

Most upvoted comments

Tested my project and MRP in 4.1 and still getting this issue.

There are some slight differences and improvements however.

  • The console doesn’t get spammed anymore.
  • The first error, “An item with the same key…”, actually appears when first running the game even before any changes are made. And the “.Net failed to load assemblies” shows after one change.
  • I don’t always have to delete the .Godot folder but sometimes I do.
  • Any changes I make to a games code after this error occurs do get reflected now.
  • [GlobalClass] won’t show up on build after this error occurs. Changes to a Resource, like adding an export, don’t show in the editor after this error occurs.
  • Possibly some weird behaviour but could also be due to the update to 4.1.

Overall still a big issue for me and is getting in the way of developing my game.

@TomNCatz I was having the same problem with a project that worked in beta 15 but not 16, I was able to fix it (in beta 17) by deleting the “temp” folder at “Project Dir”/.godot/mono/

Been hit by this myself in beta 9.0

I had some [Tool] scripts, but removing [Tool] did not fix the issue.

It appears to be being caused by assemblies not getting unloaded properly. From the godot console:

Unloading assembly load context...
Vulkan API 1.3.205 - Using Vulkan Device #0: NVIDIA - NVIDIA GeForce GTX 1050 Ti

<some game logging stuff here>
Assembly unloading is taking longer than expected...
Failed to unload assemblies. Possible causes: Strong GC handles, running threads, etc.

The deluge of errors starts immediately thereafter.

In my case, I can cause this to happen by:

  1. Starting up the editor
  2. You can build/run the project as much as you like without issue here
  3. Make a change to the code that forces script recompilation
  4. Something somewhere will kick up an exception in ScriptManagerBridge.TryReloadRegisteredScriptWithClass to do with adding a type to a dictionary that already contains that given key, always a generic class:
  modules/mono/glue/runtime_interop.cpp:1223 - System.ArgumentException: An item with the same key has already been added. Key: DisplayControlCollection`2[PawnSystem.Pawn,ClientControllerSystem.PawnUIControl]
     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 545
  1. Project can still run etc as many times as you like
  2. At the next script recompilation, the assembly fails to unload as described above and it all goes to hell

Curiously, only building from visual studio code (as opposed to the godot editor) sees the issue with TryReloadRegisteredScriptWithClass and generic classes kick off immediately. The second time you build from VSCode, either the deluge begins in the godot editor or it just outright freezes, but so long as you don’t need to edit scenes you can still work and run the project just fine from visual studio code.

Quick update, I’ve had some luck tracking this down!

The cause - in my case - appeared to be, as the ‘failed to unload assemblies’ message mentioned, strong GC handles. Specifically, static variables that would persist between reloads and potentially have handles to things that should have been deleted.

The quick tl;dr, manage your static variables responsibly. I had a few things static that really didn’t need to be, and after refactoring I can no longer reproduce the error as I mentioned previously.

@matthew798 yes that’s right. The problem seems to be caused by my C# plugin using [Tool] and has multiple references to scenes via ResourceLoader.Load<PackedScene>("uid://whatever") and json files via

var fileStream = FileAccess.Open(filePath, FileAccess.ModeFlags.Read);
var fileText = fileStream.GetAsText();
fileStream.Dispose();

The only external dependency I’m using is Newtonsoft.Json.

I have this problem too with my C# game+plugin project since 4.0 (but it got worser in 4.1). Before i just ignored it and it worked. But now in 4.1, when i build my project in Visual Studio, Godot starts to drop “.NET failed to unload assemblies” and delegate_handle errors, until i restart the engine. As a mitigation workaround for now i add the plugin instance child to GetEditorMainScreen() only when it really is pressed, so the errors start to drop only when i used the plugin, but its very annoying.

2023-07-10_19-34-46

You can try building from source with that PR and test if it fixes the issue problems for you, because the error spam is really just a symptom of the editor breaking beyond recovery and that is what the PR fixes.

If it does not (I never tried to figure out what exactly the consequences of continuing are) a lot more system information is need to even begin diagnosing these issues.

@guessy42 Interesting. I’d be curious to see what the before and after of your refactoring look like. I don’t see how a static variable would cause an issue here. Also, I don’t have any static variables in my script.

It could also be static events, or really anything that creates a strong handle that stops the assembly from being unloaded. To be honest, I’m not 100% sure what all the possible causes for stopping assemblies unloading even are.

This is the original, problematic script: https://pastebin.com/Ey7XQtGH This is the fixed one: https://pastebin.com/PjG67QEr

It’s pretty much moving static variables to singleton instance variables and adding more cleanup / safeguards. Awaiters is an autoload.

In hindsight the use of static variables in that script was honestly bound to cause problems but, well, that’s hindsight.

@RedworkDE Just tried the PR and it seems like it does indeed resolve the issue.

I get this error now after every change in the C# project but it doesn’t seem to affect anything:

Another resource is loaded from path 'res://Cube.cs' (possible cyclic resource inclusion).

Can’t reproduce with that project, but the issue seems to limited to just the error spam, so that probably gets fixed by https://github.com/godotengine/godot/pull/75533 already.

Does anyone here have an MPR for their way of causing the assembly to fail to unload? Because there are various vague things that cause issues here but nobody has actually posted a project that can be used to test things.

Unloading assembly load context...
Assembly unloading is taking longer than expected...
Failed to unload assemblies. Possible causes: Strong GC handles, running threads, etc.
ERROR: Condition "delegate_handle.value == nullptr" is true.
   at: ManagedCallable::call (modules\mono\managed_callable.cpp:92)
ERROR: Can't get method on CallableCustom "Delegate::Invoke".
   at: (core\variant\callable.cpp:377)

I found a temporary solution. Modify GodotPlugins\Main.cs Change the return false to return true in line 270. Rework “–generate-mono-glue”.

Do not use += and Callable.Form() for signal connections to the EditorPlugin. Using the

.Connect(EditorSelection.SignalName.SelectionChanged, new Callable (this, DevHelper.MethodName.XXX))

@TomNCatz I was having the same problem with a project that worked in beta 15 but not 16, I was able to fix it (in beta 17) by deleting the “temp” folder at “Project Dir”/.godot/mono/

Running 4.0 beta 17 mono edition, ran into the same issue, this solution also worked for me.