-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
.NET: Failed to unload assemblies. Please check <this issue> for more information. #78513
Comments
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? |
The workaround for this using this library is also copied below:
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 |
Thanks for the info, I somehow missed that. As an FYI, I played around with your solution trying it on a My solution was to place the code within a
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 The only library I am referencing is one I have authored. My
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:
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 |
You also seem to be using generic |
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. |
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. |
I can absolutely understand that. The problems since 4.1 are unfortunately unexpected, varied and sometimes difficult to analyse. The new As described above, some problems are related to The simplest workaround is probably to close the problematic scene tabs (mostly Otherwise, try the code listed at the top. Surprisingly, the following worked for me:
With this code, the unload works after an incorrect attempt. |
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 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
I will try today the method mentioned above by Quinn-L and put the unload handler in an |
Nope. We decided not to waste so much time with this problem and rewrite certain parts of the code in |
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 In case this is relevant, there are other node classes(such as |
|
I can't confirm, we have all classes in separate files and as soon as |
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.. |
This comment was marked as off-topic.
This comment was marked as off-topic.
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? |
@maxime4000 |
I had this error caused by using [Export] on an enum and assigning it to the MultiplayerSynchroniser. Not sure which part was the exact cause. |
This is not the case, at least not universally. I'm consistently seeing this issue in a project in which there are no shared |
Most of the time when I get this error a quick restart and build works just fine. Is there anyway to get the editor to try effectively restart and build again once if it encounters this error? |
@Whitecl4ws What would be the correct way to create Exported variables then? |
@ilexl Well for the top line, I'm exporting a non I haven't tested it but the way you would do both would be:
Note that my personal use case was very specific wherein I was using the GoDotTest test runner to run tests ontop of |
For information, I reproduced the issue by modifying the listeners (from System.Diagnostics.Trace) in the static constructor of a Node. If the scene is open in the editor, Godot fails to unload the assembly (probably because the listener registered keep being used).
|
Can anyone give me a direction on how to debug this? I'm currently facing this issue on every project rebuild. I'm not using any I'm quite stumped what could cause this, so I read through Microsoft's documentation on how to debug this. As far as I understood, you create a helper program that loads the assemblies, unloads them and then checks for errors. So far so good, but I don't know how to apply this to Godot now, since I'm not in control of loading my game's assembly. Also, just loading the assemblies from an external program does not cause any unloading issues, but I guess this is just because nothing's happening when I simply load the assemblies but don't call any functions. edit: Just to make sure, I've stopped using Rider, made a clean build of the project using Godot but was able to reproduce the issue. |
@ghtyrant You may check if you are using any unload-incompatible featrues (System.Text.Json, or the Example above) in editor reachable code ( |
@Delsin-Yu Thanks a lot. I went through all of my code again and noticed I missed two exported variables that were not properties. Now I can rebuild my project without restarting Godot. Any plans on adding a warning/error messages for such cases? |
@ghtyrant That sounds like a relatively heavy task that requires a dedicated Roslyn analyzer to go through all code paths that the editor may touch and perform syntax tree analysis; you are welcome to open up a proposal in the proposal repo and see if any community contributor is interested. |
Folks, |
Has any solution to this been found (or proposed to be fixed in the next update)? I'm running into this issue myself and I'm unsure what exactly is causing it. If it's a tool script ok. But I'd like to know what KIND of thing can cause this. Cuz at the moment it's a little confusing. |
Nothing? |
I was playing around with a [Tool]
public partial class BodyPartEditor : Node2D
{
[Export(PropertyHint.File, "*.tres")]
public string ResourcePath { get; set; }
[ExportToolButton("Save Resource")]
public Callable SaveResourceButton { get; set; }
[ExportToolButton("Load Resource")]
public Callable LoadResourceButton { get; set; }
public override void _Ready()
{
SaveResourceButton = Callable.From(SaveResource);
LoadResourceButton = Callable.From(LoadResource);
// ...
}
} I am not sure if I use the |
@jsbeckr I am having the same problem with the [Tool]
[GlobalClass]
public partial class DatasourceSqlDb : DatasourceBase<SqlConnection, DatasourceConfigSqlDb> {
[ExportGroup("Connection")]
[Export]
public override DatasourceConfigSqlDb Config { get; set; }
[ExportToolButton("Test Connection")]
public Callable TestConnectionButton => Callable.From(this.TestConnection);
...
} |
I spend 2 month on an addon. I actually planned to release it next week but as I use System.Text.Json, other dll libs, threads, async await + some more unidentified things that cause ".NET: Failed to unload assemblies." my addon now causes that error with every press of build. I can't release an addon that causes this issue whenever build is pressed!!!! From what I've read there is no usable solution yet... Please!!!! At least make a build signal or smth so I can use that to deactivate the addon/addons scripts temporarily... otherwise this addon I spent so much time on will not be usable.... I actually have worked on 2 more that just needed some polishing. I planned to release those within the year but with this error around those would also become useless...... ----- edit: I've worked on the mentioned workaround for the .net disconnect issue with chatgpt, but I don't know any c++ and have no clue if this would actually work. It would be nice if someone familiar with godots source could take a look at it: The idea is to make the build send a signal. Addons could then unload .net stuff that causes the .net disconnect. When the addons are finished unloading they would send a "I'm done signal" and godot would then start the build process. When finished there would be a "finished building signal" and the addons would load back what was unloaded before. To refine this further addons could subscribe to the build pause thing, then godot could check for all subscribed addons to finish unloading. So that addons that don't need to unload anything won't make godot pause the build process. |
@BrahRah As for unloading static caches produced by public static class JsonCacheControl
{
public static void ClearCache()
{
var assembly = typeof(System.Text.Json.JsonSerializerOptions).Assembly;
var updateHandlerType = assembly.GetType("System.Text.Json.JsonSerializerOptionsUpdateHandler");
var clearCacheMethod = updateHandlerType?.GetMethod("ClearCache", BindingFlags.Static | BindingFlags.Public);
clearCacheMethod?.Invoke(null, [null]);
}
} |
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
Footnotes
Bugsquad edit ↩ ↩2
The text was updated successfully, but these errors were encountered: