Character occasionally freezes when dying but doesn't actually register as dying

Video of the bug in action:

robloxapp-20231023-0717069 - Trim.wmv (3.2 MB)

(Normal death shown for comparison)

As you can see, occasionally the character will freeze when dying, and the .Died event will not fire on the server, but on the client. Since the death screen showed, I’m sure .Died is firing on the client, but not on the server, where I handle character respawning.

Ragdoll module (mine):

local Ragdoll = {}
Ragdoll.__index = Ragdoll

function Ragdoll.new()
	local self = {}
	self.character = nil
	
	return setmetatable(self, Ragdoll)
end

function Ragdoll:Init()
	local hum = self.character:WaitForChild("Humanoid")
	hum.BreakJointsOnDeath = false
	local humanoidRootPart = self.character:WaitForChild("HumanoidRootPart")
	
	local function died()
		--hum:ChangeState(Enum.HumanoidStateType.Physics, true)
		
		for _, joint in ipairs(self.character:GetDescendants()) do
			if joint:IsA("Motor6D") then
				local socket = Instance.new("BallSocketConstraint")
				local attachment0 = Instance.new("Attachment")
				local attachment1 = Instance.new("Attachment")
				
				attachment0.CFrame = joint.C0
				attachment1.CFrame = joint.C1
				
				socket.Attachment0 = attachment0
				socket.Attachment1 = attachment1
				--socket.LimitsEnabled = true
				--socket.TwistLimitsEnabled = true
				
				attachment0.Parent = joint.Part0
				attachment1.Parent = joint.Part1
				socket.Parent = joint.Parent
				
				joint:Destroy()
			end
		end
		
		local newFling = script:WaitForChild("Fling"):Clone()
		newFling.Attachment0 = humanoidRootPart:WaitForChild("RootAttachment")
		newFling.Parent = self.character
		
		self = nil
	end
	hum.Died:Once(died)
end

return Ragdoll

Respawn script:

local replicatedStorage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")

local maps = replicatedStorage:WaitForChild("Maps")

local function loadMap(map: Model)
	local newMap = map:Clone()
	newMap:PivotTo(CFrame.new(0, 0, 0))
	newMap.Name = "Map"
	newMap.Parent = workspace
end

local function playerAdded(player: Player)
	local function characterAdded(char)
		local hum = char:WaitForChild("Humanoid")
		
		local dead = false
		
		local function died()
			dead = true
			
			task.wait(players.RespawnTime)
			
			player:LoadCharacter()
		end
		local function healthChanged(health)
			if health < 1 then
				task.wait(players.RespawnTime)
				
				if not dead then
					player:LoadCharacter()
				end
			end
		end
		
		hum.Died:Once(died)
		hum.HealthChanged:Connect(healthChanged)
	end
	player.CharacterAdded:Connect(characterAdded)
	
	player:LoadCharacter()
end
local function playerRemoving(player)
	
end

local function roundLoop()
	while true do
		local oldMap = workspace:FindFirstChild("Map")
		if oldMap then
			oldMap:Destroy()
		end
		
		local randomMap = maps:GetChildren()[math.random(1, #maps:GetChildren())]
		loadMap(randomMap)
		
		task.wait(360)
	end
end
task.defer(roundLoop)

players.PlayerAdded:Connect(playerAdded)

(I have disabled the “Fling” object mentioned in the Ragdoll module script, which wasn’t the cause of the problem.)
I’ve also tried detecting when the player’s health is under 1, but that hasn’t worked either.
This also occurred when I let Roblox handle respawning. I need to handle respawning because I’m making a round-based system.

What can I do?

Thanks,
Fizzitix