URGENT! QueueFree() does not work C# Dispose Bool FATAL

Godot Version

Replace this line with your Godot version

Question

` I have a method to create Items that is as follows

var PackedScene = (PackedScene)GD.Load("res://Scenes/pickup_item.tscn");
		var CurrItem = (PickupItem)PackedScene.Instantiate();
		CurrItem.Position = intBlockPosition + new Vector3(0.5f,0.5f,0.5f);
		GetParent().GetNode<Node>("ItemHolder").AddChild(CurrItem);

then when the object is near the player, it does this


if(IsInstanceValid(this) && !IsQueuedForDeletion())
		{
			if ( Position.DistanceTo(Player.Instance.Position) < 0.25f)
			{
				CallDeferred("AddItemToInventory");
			}
				
		}

in the add to inventory this is how it goes down

	private void AddItemToInventory()
	{
		// Make sure this object is still valid before adding it to the inventory
		if (IsInstanceValid(this))
		{
			var itemToAdd = (Item)GD.Load("res://Items/" + item + ".tres");
			Inventory.Instance.Add(itemToAdd);

			QueueFree();
		}
		else
		{
			GD.Print("The object is no longer valid when trying to process pickup.");
		}
	}

when this is executed, the game fataly crashes with only one error "Godot.GodotObject.Dispose(bool): FATAL Condition “!Object::cast_to(p_ptr) is true”, I have been trying to fix this alone for a few weeks over and over, trying step after step. HELP`

Is there a stack trace?

1 Like

I try to add breakpoints and a stacktrace, but they wont activate. the code executes the Queuefree() without activating the catch(Exception e) instead here is a video of it Crashing if it will shine some light on this bug

This is the full error

E 0:00:40:0366   GodotObject.base.cs:122 @ void Godot.GodotObject.Dispose(bool): FATAL: Condition "!Object::cast_to<RefCounted>(p_ptr)" is true.
  <C++ Source>   modules/mono/glue/runtime_interop.cpp:169 @ godotsharp_internal_refcounted_disposed()
  <Stack Trace>  GodotObject.base.cs:122 @ void Godot.GodotObject.Dispose(bool)
                 GodotObject.base.cs:85 @ void Godot.GodotObject.Finalize()

New Users cannot upload files, so this’ll have to do

(I am using multithreading as this is a mindcrap clone)

This line looks a little confusing to me. After the item is added the api deletes Itself?

Yes, I’ve tried this method of self deletion to other objects and it had no issue, is there a better way to handle this?

this is the code I’ve written with the help of GPT since the post


	private void AddItemToInventory()
	{
		// Make sure this object is still valid before adding it to the inventory
		if (IsInstanceValid(this))
		{
			var itemToAdd = (Item)GD.Load("res://Items/" + item + ".tres");
			Inventory.Instance.Add(itemToAdd);
			try{
				QueueFree();
				
			}
			catch (Exception e)
			{
				GD.PrintErr($"Failed to	Delete {item}: {e.Message}");
				GD.PrintErr($"Stack trace: {e.StackTrace}");
			}
			
		}
		else
		{
			GD.Print("The object is no longer valid when trying to process pickup.");
		}
	}

Not sure, but reading the error you should only free objects like nodes. Resources are ref counted and will delete themselfs once the ref count goes to zero. I.e. You should not delete them manually

What class is this transitional api?

MeshInstance3D
are you suggesting adding a Memberswiseclone()?

Im not a c# guy, so im not sure what that means. But dispose sounds a lot like delete and queuefree is a delete and you should not delete refcounted resources.

What class is

Coming from?

If it is a meshinstance you should not free it. Just remove its references.

Sorry mesh instance is a node

It self Activates that Method
In _Process

    public override void _Process(double delta)
	{
		//Rotation = new Vector3(0,Rotation.Y+0.004f,0);
		
		if(IsInstanceValid(this) && !IsQueuedForDeletion())
		{
			
			if ( Position.DistanceTo(Player.Instance.Position) < 0.25f)
			{
				CallDeferred("AddItemToInventory");
			}
			
				
		}
	}

the Object is created using this

	public void Mine(Vector3I intBlockPosition, Block block)
	{
		ChunkManager.Instance.CallDeferred(ChunkManager.MethodName.SetBlock,intBlockPosition,BlockManager.Instance.Air);
		PlaySound("Mine",block.Type);
		var PackedScene = (PackedScene)GD.Load("res://Scenes/pickup_item.tscn");
		var CurrItem = (PickupItem)PackedScene.Instantiate();
		CurrItem.Position = intBlockPosition + new Vector3(0.5f,0.5f,0.5f);
		GetParent().GetNode<Node>("ItemHolder").AddChild(CurrItem);
		if(IsInstanceValid(CurrItem))
		{
			CurrItem.item = block.Type;
		}
	}

if that sheds some light on it

would that include either :

  • Triggering it in a different class (like the player)
  • Or Using GetParent().RemoveChild(this) (Doesn’t work just tested it)

How would I remove it’s references without keeping unnecessary data around?

Infound this. void Godot.Object.Finalize(): FATAL: Condition "!Object::cast_to<RefCounted>(p_ptr)" is true · Issue #68148 · godotengine/godot · GitHub

I wonder if that call deferred is happening multiple times and is setting itself up for a fatal error. Maybe you should perform the task now, or have a better latch that blocks it the first time and not later.

It is not, I am logging each time it happens and it is calling once

I STILL HAVE NOT SOLVED IT

using Godot;
using System;

public partial class PickupItem : Node3D
{
    public Item item;
    public void _on_area_3d_area_entered(Area3D area) {
        GD.Print("Entered");
        if(!IsQueuedForDeletion())
        {
            Inventory.Instance.CallDeferred("Add",item);
            CallThreadSafe("QueueFree");
        }
    }
}

Current Code
what would this “better latch” be?
@godot_team

Just put project in git and we can check what going there.

SOLVED
was using MembersWiseClone()
instead use Duplicate()
Sorry for the Headache

1 Like