How to stop an action midway using coroutines

Im having this script run an action by a player which is used to gather stuff from the ground. But Im adding a remote event to cancel the action midway.

I tried to make the whole action in a coroutine that could be canceled by the cancelActionEvent.OnServerEvent. My main problem is that I when I try to close it, it prints ''cannot resume dead coroutine. And moreover, the whole function is called everytime a player starts an action. So if they start the action, cancels it and restarts, it will create 2 cancelActionEvent.OnServerEvent detection therefor printing “cancelling (x2)”

function action(plr,model,tool,track,reward,amount,prompt)
	print("action")
	local char = plr.Character
	local hRP = char.HumanoidRootPart
	local hum = char.Humanoid
	local clone
	local actionRoutine = coroutine.create(function()
		animationRemote:FireAllClients(track)
		cameraRemote:FireClient(plr,true)
		hRP.Anchored = true
		hum.AutoRotate = false
		clone = tool:Clone()
		wait(1/3)
		hum:UnequipTools()
		clone.Parent = char
		local lookpart = model:FindFirstChild("BottomPart") or model:FindFirstChild("HumanoidRootPart")
		hRP.CFrame = CFrame.lookAt(hRP.Position, Vector3.new(lookpart.Position.X, hRP.Position.Y, lookpart.Position.Z))
		wait(13/3)
		clone:Destroy()
		wait(1/3)
		plr.leaderstats:FindFirstChild(reward).Value += amount
		hRP.Anchored = false
		hum.AutoRotate = true
		cameraRemote:FireClient(plr,false)
		plr.leaderstats.ActionTag.Value = false
		ActionManager.fadeOut(model)
	end)
	coroutine.resume(actionRoutine)
	print("Resumed")
	cancelActionEvent.OnServerEvent:Connect(function(requester)
		if requester == plr then
			print("cancelling")
			coroutine.close(actionRoutine)
			hRP.Anchored = false
			hum.AutoRotate = true
			animationRemote:FireAllClients("stop")
			cameraRemote:FireClient(plr,false)
			clone:Destroy()
			plr.leaderstats.ActionTag.Value = false
			prompt.Enabled = true
		end
	end)
end

Output:
image

DONT BOTHER ABOUT: '‘Starting the game’'

Sorry for being 3 years late, but I feel like I should still answer because no reply was given here.

cancelActionEvent issue

So, normally to fix your issue with the cancelling happenning twice on the second time (and 3 times on the 3rd time and so on) you can do the simple way and change :Connect to :Once, which basically does what the name says and just calls the function once and never again.

BUT seeing you have some logic, aka if requester == plr then, we have to take a different approach.
if we do the above method and the requester is different from the player the player will no longer be able to cancel because another requester took the function away.

so.
create an undefined variable

example, like you did with variable clone:

local CAE_Remote

(you should do this at the beginning of the function)

then assign CAE_Remote to the
cancelActionEvent.OnserverEvent
as such:

CAE_Remote = cancelActionEvent.OnServerEvent:Connect(function()

doing that will assign an RBXScriptConnection to the CAE_Remote variable, which has a “:Disconnect()” method. Now, why create an undefined variable first then define it later? So you can use the variable INSIDE the cancelActionEvent function. call CAE_Remote:Disconnect() inside the function to stop it from ever firing again.

the reason why this issue happens in the first place is because whenever the function action() is being called a new cancelActionEvent.OnServerEvent connection gets created, which is never disconnected.

About coroutine… I tried replicating the issue but I couldn’t get it, most likely because this is a 3 year old post, and this is already irrelevant.

I apologise if I disturbed you, and have a great day.