Unable to task.desynchronise() from a module

I’m running into an issue where I have a module that’s being required by a script that’s the child of an Actor instance, and I’m trying to use task.desynchronise() within that module but it’s saying that it “should only be called from a script that is a descendant of an Actor”. However, in the documentation for task.desynchronise() it says in the second paragraph that you should be able to use the function within a module as long as that module is required by a script which is the child of an actor, which is what I currently have

Server Script

This is the script that’s the child of an Actor

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local RunService = game:GetService("RunService")

local Packet = require(ReplicatedStorage.Utility.Packets.Packet)

local character = script.Parent.Parent
local characterName = character.Name

local CombatEvent = Packet(characterName .. "_Combat", Packet.NumberU8)

local stun = character:WaitForChild("Stun")

local swing = require(ServerScriptService.Character.Scripts.Combat.Light.Swing)

local function onCombatEvent(player, action)
	if player.Name ~= characterName then
		return
	end
	
	local character = player.Character
	
	if action == 1 then
		swing.perform(character)
	end
end

CombatEvent.OnServerEvent:Connect(onCombatEvent)
Module Script

This is the module that’s required by the server script

local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Debris = game:GetService("Debris")


local setStringAttribute = require(ServerScriptService.Utility.setStringAttribute)
local getStringAttribute = require(ServerScriptService.Utility.getStringAttribute)
local getTimeSinceAttribute = require(ServerScriptService.Utility.getTimeSinceAttribute)
local createHitBox = require(ReplicatedStorage.Utility.createHitBox)

local SWING_CD = 0.4 -- swap with proper weapon table later
local TOTAL_LIGHT_SWINGS = 3
local HITBOXES = {
	Vector3.new(5,5,5),
	Vector3.new(5,5,5),
	Vector3.new(5,5,5),
}
local STUN_TIME = 0.3

local light = {}

function light.perform(character)
	local combatActor = character:WaitForChild("CombatActor")
	local combatServer = combatActor:WaitForChild("CombatServer")
	
	local actor = combatActor
	local actions = combatServer:WaitForChild("Action")
	if not actions or not actor then
		warn("Character is missing CombatActor: ", actor, " or Actions: ", actions)
		return
	end
	
	local acction = getStringAttribute(actions, "action") or "None"
	if acction ~= "None" then
		return
	end
	
	local lastSwingTime = getTimeSinceAttribute(actions, "Light")
	if lastSwingTime < SWING_CD then
		return
	end
	
	local currentLightSwing = actions:GetAttribute("currentLightSwing") or 1
	if currentLightSwing > TOTAL_LIGHT_SWINGS then
		actions:SetAttribute("currentLightSwing", 1)
	end
	
	local function finish()
		actions:SetAttribute("currentLightSwing", currentLightSwing + 1)
		setStringAttribute(actions, "action", "None")
	end
	
	local root = character:WaitForChild("RootPart")
	local health = character:GetAttribute("Health") or 100
	
	local overlapParams = OverlapParams.new()
	overlapParams.FilterType = Enum.RaycastFilterType.Exclude
	overlapParams.FilterDescendantsInstances = {character}
	
	task.desynchronize()
	local hitbox = createHitBox(root.CFrame, HITBOXES[currentLightSwing], overlapParams, false)
	if not hitbox then
		return
	end
	task.synchronize()
	
	-- Visualization
	local part = Instance.new("Part")
	part.Anchored = true
	part.CanCollide = false
	part.CanQuery = false
	part.CanTouch = false
	part.CastShadow = false
	part.Material = Enum.Material.ForceField
	part.Color = Color3.fromRGB(255, 0, 0)
	part.Size = HITBOXES[currentLightSwing]
	part.CFrame = root.CFrame
	part.Parent = workspace

	Debris:AddItem(part, 0.5)
	
	local targets = {}
	for _, part in pairs(hitbox) do
		local character = part.Parent
		if character and character:IsA("Model") then
			table.insert(targets, character)
		end
	end
	
	for target, _ in pairs(targets) do
		local targetActions = target:WaitForChild("CombatActor").CombatServer.Action
		local targetAction = targetActions:GetAttribute("action") or "None"
		
		targetActions:SetAttribute("Stun", STUN_TIME)
		finish()
	end
end

return light

Picture of my setup in studio

The CombatActor gets cloned to every player, but they all use the same module scripts

Screenshot 2025-05-01 at 11.28.35 AM

Sorry if the code is a little messy I’m still prototyping things

Any help would be appreciated :pray: