godotengine / godotengine/godot

Godot crashes in Debug when C# exception is thrown (VS Code and Rider, using dotnet 8.0.204)

Open
#90,753 1 comment 0 reactions 0 assignees View on GitHub
bug crash topic:dotnet
Dominant language
C++
Stars
117k
Forks
26.8k
PR merge metrics
PR metrics pending

Description

### Tested versions

- Reproducible in all 4.2 and 4.3 version (including 2e5d2333b782a2439c4d2cb32cf9fa69d1f6d5e5) I have tested (self-built from this repo and downloadable releases).

### System information

Linux my-laptop 6.5.0-25-generic #25~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Feb 20 16:09:15 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

### Issue description

Not every, but some exceptions I throw cannot be caught and the corresponding catch block is not executed. This is only reproducible in direct or indirect executed code of a C# `_Ready()` method and only when it is executed as a follow of the node being added from a dynamically loaded `PackedScene` and won't happen in non-Debug mode:

```C#
public partial class Root : Node {
private static readonly StringName AddThrowingNodeAction = new("add_throwing_node");
private static readonly PackedScene ThrowingNodeScene = GD.Load("res://src/ThrowingNode.tscn");

public override void _Input(InputEvent @event) {
if (@event.IsAction(AddThrowingNodeAction) && @event.IsPressed()) {
AddThrowingNode();
}
}

private void AddThrowingNode() {
ThrowingNode node = ThrowingNodeScene.Instantiate();
AddChild(node);
}
}
```

```C#
using System;
using Godot;

namespace Game;

public partial class ThrowingNode : Control {
public override void _Ready() {
// Round #1
try {
throw new ArithmeticException("foobar");
}
catch (ArithmeticException) {
Console.WriteLine("Caught Round #1"); // Won't land here if using dotnet of a version before 8.0.204
}

// Round #2
try {
Convert.ToDouble("");
}
catch (Exception) {
Console.WriteLine("Caught Round #2"); // Won't land here if using dotnet of a version starting 8.0.204
}
}
}
```

```
[gd_scene load_steps=2 format=3 uid="uid://b8q5m24wqvqq3"]

[ext_resource type="Script" path="res://src/ThrowingNode.cs" id="1_0tdku"]

[node name="ThrowingNode" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_0tdku")
```

This issue hurts a lot: I cannot Debug anything any more, because the Godot app closes (crashes?) every single time on Debug when throwing the exception.

**Jetbrains Rider** will directly exit Godot and won't even stop before throwing the exception ([Details](https://youtrack.jetbrains.com/issue/RIDER-110607/Godot-app-exits-on-thrown-C-exception-without-error)).
**VS Code**, will get its started Debug Godot runtime frozen.

`Convert.ToDouble("")` should throw a `FormatException` and in other error cases an `OverflowException`. Interestingly, throwing those directly won't trigger the crash: They get caught. Only when causing `Convert.ToDouble(...)` to fail, it crashes and, like before, the debugger won't stop at all at exception. This happens with `8.0.204`.

Console output:
```
RD-241.14494.225, JRE 17.0.10+8-b1207.12x64 JetBrains s.r.o., OS Linux(amd64) v6.5.0-25-generic, screens 1920.0x1080.0
.NET Core v8.0.1 x64 (Server GC)
Logs: https://dotnet-ea.services.jetbrains.com/files/small/968660d4-ca36-4f3f-9f93-541647b824d0/rider-logs-attachment.tar.xz
Affected versions: 2024.1 RC 1 (241.14494.225)
```

Dotnet:
```
$ dotnet --version
8.0.204
```

```
$ dotnet sdk check
.NET SDKs:
Version Status
------------------------
8.0.204 Up to date.

Try out the newest .NET SDK features with .NET 9.0.100-preview.2.24157.14.

.NET Runtimes:
Name Version Status
------------------------------------------------------
Microsoft.AspNetCore.App 8.0.4 Up to date.
Microsoft.NETCore.App 8.0.4 Up to date.

The latest versions of .NET can be installed from https://aka.ms/dotnet-core-download. For more information about .NET lifecycles, see https://aka.ms/dotnet-core-support.
```

Issue is reproducible with any Net version (6.0, 7.0, 8.0):
```
net8.0
```

### Steps to reproduce

- Download the attached project
- Run the project in DEBUG
- Press `O` (the letter) key
- Notice crash/freeze (or if not reproducible in your environment `Caught Round #1` and `Caught Round #2` in the console output)

### Minimal reproduction project (MRP)

[throwing-demo2.zip](https://github.com/godotengine/godot/files/14998155/throwing-demo2.zip)

Contributor guide

Open the contributing guide

Research direction

Start by running the attached throwing-demo2.zip project in Debug and reproducing the crash or freeze after pressing O. Trace the C# execution path from a dynamically loaded PackedScene into ThrowingNode._Ready(), comparing the behavior across the stated .NET versions and debuggers. Done means the example's exceptions are caught without Godot exiting or the debug runtime freezing.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, godot
Domain
game-dev, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.