Can't cancel thread

I have an obby race type game. When the round ends or all the players die/beat the obby. It uses task.cancel to cancel the previous intermission and start a new one. However if the game ends from the time running it out, it gives an error “ServerScriptService.Round:159: cannot cancel thread”

function removeplayer(plr)
	plr:WaitForChild("InGame").Value = false
	local character = plr.Character
	local root = character:WaitForChild("HumanoidRootPart")
	root.Velocity = Vector3.zero
	character:MoveTo(workspace.SpawnLocation.Position + Vector3.new(0,5,0))
	local position = table.find(playerinround, plr)
	if position then
		table.remove(playerinround, position)
		print(playerinround)
	end
	updatelist(plr)
end
function generatestages()
	repeat 
		local stage = game.ReplicatedStorage.Stages:GetChildren()[math.random(1, #game.ReplicatedStorage.Stages:GetChildren())]
		if not table.find(stages_added, stage.Name) then

			local stagenew = stage:Clone()
			table.insert(stages_added, stage.Name)
			stagenew.Parent = workspace.StagesCopy			
			stagenew:PivotTo(workspace.ObbyAreas["ObbyArea".. #stages_added].CFrame)
		end
		task.wait()
	until #stages_added == 5
end
local function Intermission_Timer()
	while wait() do
		status.Value = "Waiting for Players..."
	    repeat wait() until #game.Players:GetPlayers() >= 1
        for _, v in pairs(workspace.StagesCopy:GetChildren()) do
			v:Destroy()
		end

		stages_added = {}
		RoundPlaying.Value = false
		for i = intermission_length, 0, -1 do
			wait(1)
			status.Value = "Round will begin in ".. TimeAbbreviate.Convert(i)
		end
		status.Value = ""
		generatestages()
		RoundPlaying.Value = true
		print(stages_added)
		for _, plr in pairs(game.Players:GetPlayers()) do
			if plr:WaitForChild("Playing").Value == true then
				remotevents.ChangeControls:FireClient(plr, false)
			end

		end
		task.wait(2)
		for _, plr in pairs(game.Players:GetPlayers()) do
			if plr:WaitForChild("Playing").Value == true then
				remotevents.CountDown:FireClient(plr)
			end

		end

		task.wait(4)
		lavatween:Play()
		for _, plr in pairs(game.Players:GetPlayers()) do
			if plr:WaitForChild("Playing").Value == true then
				remotevents.StartRound:FireClient(plr)
			end
		end


		for i = roundlength, 0, -1 do
			wait(1)
			status.Value = TimeAbbreviate.Convert(i)
		end
		for _, plr in pairs(game.Players:GetPlayers()) do
			if plr:WaitForChild("InGame").Value == true then
				removeplayer(plr)
			end

		end
		lavatween:Cancel()
		restartLava()
		
	end
end

local interfunc = task.spawn(Intermission_Timer)
function updatelist(plr)
	if table.find({0, 1, 2}, #playerinround) then
		giveplacing(plr)
	end
	if #playerinround == 0 then

		task.wait(2)
		lavatween:Cancel()
		restartLava()
		for _, v in pairs(workspace.StagesCopy:GetChildren()) do
			v:Destroy()
		end
		if interfunc  then
			task.cancel(interfunc)
		end

		status.Value = ""
		stages_added = {}
		RoundPlaying.Value = false
		task.wait(5)
		interfunc = task.spawn(Intermission_Timer)
	end
	print(playerinround)
	for i, v in pairs(game.ReplicatedStorage.Placings:GetChildren()) do
		print(v, v.Value)
	end
end

The error is on this line
task.cancel(interfunc)

1 Like

I’m not exactly sure but I believe it’s because the thread is still running. Try coroutine.yield(interfunc) then canceling it.

I think you should not spawn interfunc outside any logic code. You spawn it here as a start point, so keep it within this function, or keep it nil until you use it in this function. i.e. find some logic that you can always spawn it through the same line of code and in the same scope.

		status.Value = ""
		stages_added = {}
		RoundPlaying.Value = false
		task.wait(5)
		interfunc = task.spawn(Intermission_Timer)

Especially when you call updatelist(plr) in RemovePlayer() and localfunc has already been scoped here local interfunc = task.spawn(Intermission_Timer), where this definition has already been compiled and possibly executed.

I forgot to update, I had fixed the issue by checking every second in the for loop where it would say the time left in the round if a variable was set to true. That if statement would be detected then use return to end the Intermission_Timer function, and then it would redo the loop. Thanks for the help though!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.