Weird error when stopping Play Solo

So I was doing some play testing in roblox studio, and I made an ingame script edit. Then I disabled and re-enabled the script and tried to see if it was running. It didn’t run, so I clicked the stop button. After then, the following message appeared on my console:

“Script that implemented this callback has been destroyed.” Probably something internal.
I took a screenshot of the interface

and got spammed with these:

It’s still going as I type this

Anyways, figured I’d post a bug report so you guys can look into it. This is the first time it’s ever happened. Here’s a full copy of the output below:

Output.txt (36.6 KB)

2 Likes

There is an existing topic about using the BindToClose function and DataStore causing issues with studio. I’m not updated with the topic, so I’m not sure if it has been solved. Looking at what your output says, the error is pretty similar to what other have said about using BindToClose.

Edit:
In my current understanding, the error occurs when studio tries to close a running server, but a script is trying to process/do more after the game is meant to shutdown. This is because of Yielding Functions, which is common with data stores and wait()

1 Like

Also having this issue, but there’s a simple solution.
Create a BindableEvent in an easily accessible place, and put this script in it:

game:BindToClose(function()
	script.Parent:Fire()
end)

No issues if you destroy anything that uses that BindableEvent, and other than the lack of issues you get the exact same results.
Obviously it would make more sense just having a regular game closing event, but until (if ever) such a thing is added this is fine.

EDIT: This doesn’t actually work exactly the same.
game:BindToClose can stall the shutdown of a server until the thread finishes executing.
However, if it fires a BindableEvent to start shutdown functions, then that creates new threads, threads that are not waited on meaning it’s possible for the server to shut down while executing shutdown functions.
This difference is incredibly important for things that take time, like writing things to the data store or teleporting players.
Considering that those are the only two things you could want the game to do as the server shuts down, what I’ve described with a BindableEvent is actually completely useless.
So, to actually get identical behaviour to directly using BindToClose, once again have a script in a BindableEvent, but this time that script is:

--Behaviourally identical to game:BindToClose, except that it does not create an error in studio if a bound script was destroyed.
--Use by firing the parent BindableEvent with a function, and the script that function is contained in.

Bound = {}

script.Parent.Event:Connect(function(func, Script)
	table.insert(Bound, {func = func, Script = Script})
	
	Script.AncestryChanged:Connect(function()
		if not Script:IsDescendantOf(game) then
			for i, Pair in pairs(Bound) do
				if Pair.Script == Script then
					table.remove(Bound, i)
					return
				end
			end
		end
	end)
end)

game:BindToClose(function()
	local remaining = #Bound
	
	if remaining > 0 then
		local FinishedEvent = Instance.new('BindableEvent')
	
		for _, Pair in pairs(Bound) do
			spawn(function()
				local status, err = pcall(Pair.func)
				remaining = remaining-1
				if remaining <= 0 then
					FinishedEvent:Fire()
				end
				if not status then
					error(err)
				end
			end)
		end
		
		FinishedEvent.Event:Wait()
	end
end)
1 Like