godot icon indicating copy to clipboard operation
godot copied to clipboard

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

Open RIKDXHQ11 opened this issue 1 year ago • 32 comments

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

RIKDXHQ11 avatar Dec 13 '22 19:12 RIKDXHQ11

Just wanted to chime in and say that I am also facing this issue and it's blocking. I'm using the official build of beta 9. Not complaining or anything, I know it's beta :).

Is this related to, but not fixed by #69194? If so, do we know how to work around it for the time being?

matthew798 avatar Dec 21 '22 17:12 matthew798

Just wanted to provide some more context:

This issue occurs for me only when a C# script marked as [Tool] is attached to a node, and the script loads 1 or more resources.

Here is the code that causes the error, in my case:

[Tool]
public partial class LevelManager : Node3D
{
	public override void _Ready()
	{
	    LoadBlocks();
		
	    if(_levelNode == null){
		_levelNode = new Node3D() {Name = "Level"};
		AddChild(_levelNode);
		if(Engine.IsEditorHint()){
			_levelNode.Owner = this;
		}
	    }
	    LoadLevel();
	}
        
        private void LoadBlocks(string path = "Prefabs/Blocks"){
	    _blockList.Clear();

	    var files = Directory.GetFiles(path, "*.tscn", SearchOption.AllDirectories);

	    foreach(String file in files){
		var filename = Path.GetFileNameWithoutExtension(file);
		_blockList[filename] = GD.Load<PackedScene>($"res://{path}/{filename}.tscn");
	    }
	}
}

If either the [Tool] attribute is removed or the LoadBlocks method is commented out, the issue does not occur. I hope this helps.

matthew798 avatar Dec 23 '22 20:12 matthew798

I was running into this. In my case it seems to have been caused by using a .NET 7 SDK instead of .NET 6. dotnet defaults to using the latest installed SDK and I have both installed. Adding the following global.json file to the root of the project fixed the issue.

{
  "sdk": {
    "version": "6.0.404"
  }
}

Currently running Godot 4 Beta 10 on MacOS Ventura 13.0.1.

ghost avatar Dec 29 '22 20:12 ghost

{
  "sdk": {
    "version": "6.0.404"
  }
}

This unfortunately hasn't fixed it in my case. On the next build after launching I get the same error as above. The messages from the terminal are:

Copying Godot Offline Packages...
Unloading assembly load context...
Assembly unloading is taking longer than expected...
Failed to unload assemblies. Possible causes: Strong GC handles, running threads, etc.
ERROR: .NET: Failed to unload assemblies.
   at: (modules/mono/mono_gd/gd_mono.cpp:504)
ERROR: Condition "delegate_handle.value == nullptr" is true.
   at: call (modules/mono/managed_callable.cpp:92)
ERROR: Can't get method on CallableCustom "Delegate::Invoke".
   at: (core/variant/callable.cpp:333)
ERROR: Error calling from signal 'timeout' to callable: 'Node::': Method not found.

I'm running: 4.0.beta10.mono (As far as I can tell this has affected every build since the .net 6 merge.) Windows 10 pro x64

dotnet --info shows: .NET SDKs installed: 2.1.202 [C:\Program Files\dotnet\sdk] 2.1.401 [C:\Program Files\dotnet\sdk] 2.1.402 [C:\Program Files\dotnet\sdk] 2.1.526 [C:\Program Files\dotnet\sdk] 3.1.120 [C:\Program Files\dotnet\sdk] 3.1.201 [C:\Program Files\dotnet\sdk] 3.1.426 [C:\Program Files\dotnet\sdk] 5.0.104 [C:\Program Files\dotnet\sdk] 5.0.408 [C:\Program Files\dotnet\sdk] 6.0.112 [C:\Program Files\dotnet\sdk] 6.0.307 [C:\Program Files\dotnet\sdk] 6.0.400 [C:\Program Files\dotnet\sdk] 6.0.404 [C:\Program Files\dotnet\sdk]

gallsy avatar Dec 30 '22 00:12 gallsy

@gallsy can you confirm that you are running a [Tool] script and it loads a resource from disk?

matthew798 avatar Dec 30 '22 03:12 matthew798

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

gallsy avatar Dec 30 '22 03:12 gallsy

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.

guessy42 avatar Dec 30 '22 15:12 guessy42

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.

guessy42 avatar Jan 15 '23 10:01 guessy42

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

matthew798 avatar Jan 15 '23 13:01 matthew798

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

guessy42 avatar Jan 16 '23 09:01 guessy42

I don't know if my circumstances match everyone else's, but I am seeing this issue in beta 16 as well.

I have found that if I hit "Build" manually before hitting the play button I do not seem to get the errors. Also, I noticed that if I do not hit "Build" before hitting play, even if I have mistakes in my code that should prevent compile it still runs the app. I do not need to hit "Build" every time before I hit play if I have not made code changes. I suspect there is an issue causing the build to either not happen or not complete in time when you just press play.

As a note, this holds true whether I am compiling for .net6.0 or .net7.0

TomNCatz avatar Jan 31 '23 18:01 TomNCatz

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

XenokNyx avatar Feb 01 '23 21:02 XenokNyx

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

MagmaGuy avatar Feb 02 '23 07:02 MagmaGuy

I am now on version rc.3, after deleting the temp folder, the issue would still occur after some code changes and rebuilding.

tjp1205 avatar Feb 24 '23 08:02 tjp1205

I'm also getting this in RC.6, happens quite randomly (but frequent) when building (or playing)

nobbele avatar Feb 27 '23 19:02 nobbele

This still happens in stable.

It happens almost every single time I make a change to a C# script, no matter how simple the project is. Just rotating a cube is enough to cause this.

DomiStyle avatar Mar 02 '23 10:03 DomiStyle

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

magian1127 avatar Mar 02 '23 17:03 magian1127

I am also facing this problem in 4.0 Stable. The MRP is simply setting and using any static fields in a Godot-based class's static constructor.

My temporary solution is to make sure all static fields and properties are not be set in ModuleInitializer and static constructors of any classes that extends Godot classes, such as Node, Control, etc..

EDIT: "All static fields and properties" includes the ones in any user-written classes, no matter whether the class extends Godot.Node.

emowen4 avatar Mar 19 '23 04:03 emowen4

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.

RedworkDE avatar Mar 31 '23 15:03 RedworkDE

@RedworkDE It happens pretty much in any project for me once I make a single change to a C# script, but here's a really simple project:

GodotTimeoutIssue.zip

Here's a short video on how I can trigger it:

https://user-images.githubusercontent.com/975131/229175342-72aa6714-35c6-4d4e-a71b-88b1b811788e.mp4

DomiStyle avatar Mar 31 '23 16:03 DomiStyle

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.

RedworkDE avatar Mar 31 '23 18:03 RedworkDE

It's not just log spam for me unfortunately.

If I run the project one more time without restarting once the errors come up all script export variables will be reset to 0 in the editor which is a massive pain to resolve on larger projects.

DomiStyle avatar Mar 31 '23 18:03 DomiStyle

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.

RedworkDE avatar Mar 31 '23 19:03 RedworkDE

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

DomiStyle avatar Mar 31 '23 21:03 DomiStyle

JZGLtest.zip

After loading the plugin, click the arrow position on the screenshot. Then add or remove [Export] in the cs file (the method attribute should also trigger), and finally rebuild the solution with VS. Godot reported an error. image

Then using #75533 will cause other problems.

magian1127 avatar Apr 01 '23 08:04 magian1127

I updated to the 4.1 beta 1 and I'm still getting this issue. It's really preventing me from making progress. It happens very reliably for me. Basically I have the game running and then reload the scene twice and I'm locked out basically.

Essentially this comment

However I have to delete the projects .godot folder in the project before reopening the editor to fix the issue.

I'm on Fedora Silverblue 38, with VS Code. I haven't got any [Tool]s.

After the first reload (Step 4):

Details

  modules/mono/glue/runtime_interop.cpp:1325 - System.ArgumentException: An item with the same key has already been added. Key: Presenter`2[FundsModel,FundsView]
     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
  modules/mono/glue/runtime_interop.cpp:1325 - System.ArgumentException: An item with the same key has already been added. Key: Presenter`2[UptimeModel,UptimeView]
     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
  modules/mono/glue/runtime_interop.cpp:1325 - System.ArgumentException: An item with the same key has already been added. Key: ArrayPresenter`2[AppListModel,AppModel]
     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
  modules/mono/glue/runtime_interop.cpp:1325 - System.ArgumentException: An item with the same key has already been added. Key: Presenter`2[AppListModel,IGridView]
     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
  modules/mono/glue/runtime_interop.cpp:1325 - System.ArgumentException: An item with the same key has already been added. Key: ArrayPresenter`2[IdeaListModel,IdeaModel]
     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
  modules/mono/glue/runtime_interop.cpp:1325 - System.ArgumentException: An item with the same key has already been added. Key: Presenter`2[IdeaListModel,IGridView]
     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

The error seems to reference a parent class I have made:
public abstract partial class Presenter<M, V> : MarginContainer where M : Resource where V : class {}
public partial class FundsPresenter : Presenter<FundsModel, FundsView> {}
public partial class IdeaListPresenter : ArrayPresenter<IdeaListModel, IdeaModel> {}
etc.

Then I get this error on repeat on the second reload (Step 6):


.NET: Failed to unload assemblies. // This line doesn't repeat
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:1080 - Error calling from signal 'timeout' to callable: 'Node::': Method not found.

I don't mind providing my entire project if it helps diagnose the problem, though it's quite messy. It just takes commenting and uncommenting a line to cause the issue. I'll do some more research and see if I can simplify the reproduction.

Edit: Well I created a simple reproduction. Let me get a write up of it and tidy it up then I'll post it.

Here it is, there's a readme in the project: BugTest-70026.zip Let me know if there's any issues. It's easier to recreate in my project but this should hopefully provide what's needed

dannymate avatar Jun 08 '23 18:06 dannymate

@dannymate In my case the issue in your reproduction appears in 4.1 beta 1, but running in 4.0 stable or 4.0.3 stable doesn't cause the issue for some reason. I guess 4.1 beta changes something? I also having this issue in my own project that appears in 4.0 stable and in 4.1 beta 1.

paochapro avatar Jun 09 '23 00:06 paochapro

Well from what I gather it seems the first error, with the dictionary entries, is related to ScriptManagerBridge.cs line 579 in which it tries to add the Type which is loaded from an assembly to a ScriptTypeBiMap object.

Inside the ScriptTypeBiMap it tries to add the Type as a key but it seems duplicated. I'm not sure why it's Presenter<FundsModel, FundsView> instead of FundsPresenter for example but it seems how it figures out the Type may be part of the problem.

Another thing that could help is adding checking for duplicated keys in ScriptTypeBiMap before adding to dictionary or using TryAdd.

I'm working off the assumption that the second error is a direct byproduct of the first error.

Edit: Unsure if this TODO is related: https://github.com/godotengine/godot/blob/37d1dfef9d81aade27ab0c56fc6b6f12f6a08045/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.types.cs#LL20C1-L21C1

dannymate avatar Jun 11 '23 13:06 dannymate

I'm experiencing the same problem in 4.0.3 stable and I have had this problem in previous versions (of Godot 4) as well. It even happens if I have an empty scene set as the main scene with nothing else (no scripts whatsoever) attached to it. Sometimes it happens when I start a new project. And sometimes I make a change to my C# class (just anything, really) and suddenly I'm getting that same repeating error and I have to restart Godot to make it disappear (only for it to come back when I hit play).

soenanda avatar Jun 21 '23 08:06 soenanda

this problem is present in version 4.0.3 of c#. problem is stable.

N0zzy avatar Jun 22 '23 08:06 N0zzy