Placement system disconnection issue

I have a placement system that works almost perfectly - apart from one bug where when the player ‘cancels placement’ and attempts to place again, the function PlaceObject is called multiple times. I have deduced this to be some sort of issue with disconnecting but I can’t seem to find the issue.

Script
function PlacingMode(i)
	
	InPlacingMode = true
	Object = script:FindFirstChild(i):Clone()
	Object.Parent = game.Workspace
	
	PlaceObject()
	Mouse.TargetFilter = Object
	SelectionBox.Adornee = Object

	game:GetService("RunService").Heartbeat:Connect(function()
		if InPlacingMode then
			local OldCFrame = Object:GetPrimaryPartCFrame()
			local NewCFrame = CFrame.new(RoundAToB(math.clamp(Mouse.Hit.X, Base.Position.X-Base.Size.X/2, Base.Position.X+Base.Size.X/2), Increment), Base.Position.Y+1, RoundAToB(math.clamp(Mouse.Hit.Z, Base.Position.Z-Base.Size.Z/2, Base.Position.Z+Base.Size.Z/2), Increment)) * CFrame.Angles(0, math.rad(Rotation), 0)
			SelectionBox.Color3 = Color3.fromRGB(34, 235, 124)
			Object:SetPrimaryPartCFrame(OldCFrame:lerp(NewCFrame, 0.4))							
			ObjectIsColliding = false
			for i, v in pairs(GetTouchingParts(Object.PrimaryPart)) do
				if v.Name == "PrimaryPart" then
					ObjectIsColliding = true
					SelectionBox.Color3 = Color3.fromRGB(243, 72, 72)
				end
			end
		end
	end)
	
	game:GetService("UserInputService").InputEnded:Connect(function(InputObject, GameProcessedEvent)
		if InputObject.KeyCode == Enum.KeyCode.E and not GameProcessedEvent and InPlacingMode then
			wait(0.05)
			StopPlacing()
		end
	end)
		
	game:GetService("UserInputService").InputEnded:Connect(function(InputObject, GameProcessedEvent)
		if InputObject.KeyCode == Enum.KeyCode.R and not GameProcessedEvent and InPlacingMode then
			if Rotation >= 360 then
				Rotation = 0
			end
			Rotation = Rotation + 90
		end
	end)

end
	
function PlaceObject()
	
	print("PlaceObject()")
	
	if InPlacingMode then
		Connection = Mouse.Button1Down:Connect(function()
			Connection:Disconnect()
			local Output = ReplicatedStorage:FindFirstChild("PlaceRequest", true):InvokeServer(Object.Name, PlacementSystemModule.ObjectsTable[Object.Name], CFrame.new(RoundAToB(math.clamp(Mouse.Hit.X, Base.Position.X-Base.Size.X/2, Base.Position.X+Base.Size.X/2), Increment), Base.Position.Y+1, RoundAToB(math.clamp(Mouse.Hit.Z, Base.Position.Z-Base.Size.Z/2, Base.Position.Z+Base.Size.Z/2), Increment)) * CFrame.Angles(0, math.rad(Rotation), 0))
			OutputModule.Output(Output[1], Output[2])
			if Output[3] == true then
				StopPlacing()
			else
				PlaceObject()
			end
		end)
	end

end

function StopPlacing()
	
	Object:Destroy()
	if not Mouse.Target then
		return
	end
	if InPlacingMode then
		Mouse.TargetFilter = nil
		InPlacingMode = false
	end
	
end

Please tell me where I have gone wrong. Thanks.

You seem to be disconnecting the connection too early.
Try doing this:

function PlaceObject()
	print("PlaceObject()")
	
	if InPlacingMode then
        local Connection = nil
        
		Connection = Mouse.Button1Down:Connect(function()
			local Output = ReplicatedStorage:FindFirstChild("PlaceRequest", true):InvokeServer(Object.Name, PlacementSystemModule.ObjectsTable[Object.Name], CFrame.new(RoundAToB(math.clamp(Mouse.Hit.X, Base.Position.X-Base.Size.X/2, Base.Position.X+Base.Size.X/2), Increment), Base.Position.Y+1, RoundAToB(math.clamp(Mouse.Hit.Z, Base.Position.Z-Base.Size.Z/2, Base.Position.Z+Base.Size.Z/2), Increment)) * CFrame.Angles(0, math.rad(Rotation), 0))
			OutputModule.Output(Output[1], Output[2])
			if Output[3] == true then
				StopPlacing()
			else
				PlaceObject()
			end
			Connection:Disconnect()
		end)
	end
end

Just amended my script with this, and it doesn’t fix the complete issue however after every ‘InPlacingMode session’ it seems to ‘reset’ (which is good) until the player cancels the placement again and the bug still persists.