AnimationTrack limit of 256 tracks for one Animator exceeded, new animations will not be played

I am getting this error within my game.
image

I have quiet a lot of animations in my game (dash animation, double jump, pickaxe swing, sword swing, bat swing)

I think the major issue causing this is that I have giant leaderboards for each major stat in my game.

The #1 player is displayed on the top of the leaderboard, and updated every 2 minutes.

This reloads the rigged to the new player and applies a random dance animation to the rig.

I BELIEVE this is the issue, however, I have never had this error before and am not sure where to begin even looking for how to fix it!

Any insight would be helpful!

I would assume this means that you can only load 256 animations onto one animator at one time. Are you loading all the potential dance animations to the rig at once? If so, a solution could be to pick a random animation and only load that one before playing it. I’m not sure though, since I’ve never encountered that error before.

1 Like

I am defining all possible dance animations at the top of the script:

Summary
local DANCE_ANIM_IDS = {
	"rbxassetid://112546761278570", "rbxassetid://92277445768851",
	"rbxassetid://78936477286329", "rbxassetid://73580191044993",
	"rbxassetid://129245681352728", "rbxassetid://126806545353767",
	"rbxassetid://125262177120267", "rbxassetid://120619109566330",
	"rbxassetid://110621641901297", "rbxassetid://95734131037432",
	"rbxassetid://125237774103542", "rbxassetid://92263601861863",
	"rbxassetid://124523990124968", "rbxassetid://124441082067052",
	"rbxassetid://80178915788662",  "rbxassetid://93886861904250",
	"rbxassetid://118190145707853", "rbxassetid://107682172041660",
	"rbxassetid://110764344482160", "rbxassetid://74743663547415",
	"rbxassetid://108293915786723", "rbxassetid://88485361561231",
	"rbxassetid://111727007599426", "rbxassetid://87645436556573",
	"rbxassetid://83111406797769",  "rbxassetid://72409756539267",
	"rbxassetid://127761997509649", "rbxassetid://102624989804510",
	"rbxassetid://72969755579148",
}

And then randomly selecting one to play;

Summary
	if animator then
		local anim = Instance.new("Animation")
		anim.AnimationId = DANCE_ANIM_IDS[math.random(1, #DANCE_ANIM_IDS)]
		local track = animator:LoadAnimation(anim)
		track.Looped = true
		track:Play()
	end

This repeats 6 times every 2 minutes, as the top players are updated

Do you reload the rig even if the player doesn’t change, or is the reloading step skipped if it’s not needed?

1 Like

Do you ever stop the AnimationTrack?

1 Like

Here is the full update rig function:

Summary
local function applyTopPlayerToRig(statName, rig)
	if not rig then return end

	local statFolder = LeaderboardData:FindFirstChild(statName)
	if not statFolder then return end

	local topEntry = statFolder:FindFirstChild("1")
	if not topEntry then return end

	local userId = topEntry:GetAttribute("UserId")
	if not userId then return end

	local userDesc
	local success = pcall(function()
		userDesc = Players:GetHumanoidDescriptionFromUserId(userId)
	end)

	if not success or not userDesc then return end

	local displayName = Players:GetNameFromUserIdAsync(userId)
	local newRig = Players:CreateHumanoidModelFromUserId(userId)
	if not newRig then return end

	newRig.Name = rig.Name
	newRig.Parent = rig.Parent
	newRig:SetPrimaryPartCFrame(rig:GetPrimaryPartCFrame())
	rig:Destroy()

	-- Optional Scaling
	pcall(function()
		userDesc.HeadScale = 4.4
		userDesc.DepthScale = 4.4
		userDesc.WidthScale = 4.4
		userDesc.HeightScale = 4.4
		userDesc.BodyDepthScale = 4.4
		userDesc.BodyHeightScale = 4.4
		userDesc.BodyWidthScale = 4.4
	end)

	local humanoid = newRig:FindFirstChildOfClass("Humanoid")
	if humanoid then
		pcall(function()
			humanoid:ApplyDescription(userDesc)
		end)
		humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
		humanoid.PlatformStand = true
	end

	local root = newRig:FindFirstChild("HumanoidRootPart")
	if root then
		root.Anchored = true
		local originalCFrame = root.CFrame
		RunService.Heartbeat:Connect(function()
			if root and root.Parent then
				root.CFrame = originalCFrame
			end
		end)
	end

	local animator = humanoid and humanoid:FindFirstChildWhichIsA("Animator")
	if not animator and humanoid then
		animator = Instance.new("Animator")
		animator.Parent = humanoid
	end

	if animator then
		local anim = Instance.new("Animation")
		anim.AnimationId = DANCE_ANIM_IDS[math.random(1, #DANCE_ANIM_IDS)]
		local track = animator:LoadAnimation(anim)
		track.Looped = true
		track:Play()
	end

	attachBillboardToRig(newRig, displayName, statName)
end

BUT this part here:

	local displayName = Players:GetNameFromUserIdAsync(userId)
	local newRig = Players:CreateHumanoidModelFromUserId(userId)
	if not newRig then return end

Should be stopping a new rig from loading in?

The only part of the code that relates to the animation is what I already posted above:

    if animator then
		local anim = Instance.new("Animation")
		anim.AnimationId = DANCE_ANIM_IDS[math.random(1, #DANCE_ANIM_IDS)]
		local track = animator:LoadAnimation(anim)
		track.Looped = true
		track:Play()
	end

So I need to stop the previous animation before loading the new one?
How do I go about tracking a currently playing animation exactly?

Here is the full code for full context:

Summary
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")

-- ⏱️ Wait for leaderboard data to be populated
local MAX_WAIT = 15
local elapsed = 0
while not ReplicatedStorage:FindFirstChild("LeaderboardData") and elapsed < MAX_WAIT do
	task.wait(1)
	elapsed += 1
end

local LeaderboardData = ReplicatedStorage:FindFirstChild("LeaderboardData")
if not LeaderboardData then
	warn("⚠️ LeaderboardData not found in ReplicatedStorage after waiting.")
	return
end

local TopPositionsFolder = Workspace:WaitForChild("Leaderboards"):WaitForChild("TopPositions")

local UPDATE_INTERVAL = 120 -- seconds

local DANCE_ANIM_IDS = {
	"rbxassetid://112546761278570", "rbxassetid://92277445768851",
	"rbxassetid://78936477286329", "rbxassetid://73580191044993",
	"rbxassetid://129245681352728", "rbxassetid://126806545353767",
	"rbxassetid://125262177120267", "rbxassetid://120619109566330",
	"rbxassetid://110621641901297", "rbxassetid://95734131037432",
	"rbxassetid://125237774103542", "rbxassetid://92263601861863",
	"rbxassetid://124523990124968", "rbxassetid://124441082067052",
	"rbxassetid://80178915788662",  "rbxassetid://93886861904250",
	"rbxassetid://118190145707853", "rbxassetid://107682172041660",
	"rbxassetid://110764344482160", "rbxassetid://74743663547415",
	"rbxassetid://108293915786723", "rbxassetid://88485361561231",
	"rbxassetid://111727007599426", "rbxassetid://87645436556573",
	"rbxassetid://83111406797769",  "rbxassetid://72409756539267",
	"rbxassetid://127761997509649", "rbxassetid://102624989804510",
	"rbxassetid://72969755579148",
}

local STAT_TO_POSITION_NAME = {
	Coins = "CoinPosition",
	Kills = "KillPosition",
	Hatches = "HatchPosition",
	Rebirths = "RebirthPosition",
	Steals = "StealPosition",
	Time = "TimePosition",
}

local function addUIStrokeTo(label)
	local stroke = Instance.new("UIStroke")
	stroke.ApplyStrokeMode = Enum.ApplyStrokeMode.Contextual
	stroke.Thickness = 10
	stroke.Parent = label
end

local function attachBillboardToRig(rig, displayName, _)
	local existingGui = rig:FindFirstChild("TopBillboard")
	if existingGui then existingGui:Destroy() end

	local billboard = Instance.new("BillboardGui")
	billboard.Name = "TopBillboard"
	billboard.Adornee = rig:FindFirstChild("Head") or rig:FindFirstChild("HumanoidRootPart")
	billboard.Size = UDim2.new(0, 140, 0, 40)
	billboard.StudsOffset = Vector3.new(0, 10, 0)
	billboard.AlwaysOnTop = true
	billboard.MaxDistance = 150
	billboard.Parent = rig

	local usernameLabel = Instance.new("TextLabel")
	usernameLabel.Size = UDim2.new(1, 0, 0.5, 0)
	usernameLabel.BackgroundTransparency = 1
	usernameLabel.TextScaled = true
	usernameLabel.TextColor3 = Color3.fromRGB(255, 255, 255)
	usernameLabel.TextStrokeTransparency = 0.5
	usernameLabel.Font = Enum.Font.GothamBold
	usernameLabel.Text = displayName
	usernameLabel.Parent = billboard
	addUIStrokeTo(usernameLabel)

	local rankLabel = Instance.new("TextLabel")
	rankLabel.Size = UDim2.new(.6, 0, 0.5, 0)
	rankLabel.Position = UDim2.new(0, 0, 0.5, 0)
	rankLabel.BackgroundTransparency = 1
	rankLabel.TextScaled = true
	rankLabel.TextColor3 = Color3.fromRGB(255, 200, 50)
	rankLabel.TextStrokeTransparency = 0.5
	rankLabel.Font = Enum.Font.GothamBold
	rankLabel.Text = "RANK #1"
	rankLabel.Parent = billboard
	addUIStrokeTo(rankLabel)

	task.spawn(function()
		local hue = 0
		while rankLabel and rankLabel.Parent do
			hue = (hue + 0.005) % 1
			rankLabel.TextColor3 = Color3.fromHSV(hue, 1, 1)
			task.wait()
		end
	end)
end

local function clearAppearanceFromRig(rig)
	for _, item in ipairs(rig:GetDescendants()) do
		if item:IsA("Accessory") or item:IsA("Shirt") or item:IsA("Pants")
			or item:IsA("ShirtGraphic") or item:IsA("BodyColors")
			or item:IsA("CharacterMesh") or item:IsA("HumanoidDescription") then
			item:Destroy()
		end
	end
end

local function applyTopPlayerToRig(statName, rig)
	if not rig then return end

	local statFolder = LeaderboardData:FindFirstChild(statName)
	if not statFolder then return end

	local topEntry = statFolder:FindFirstChild("1")
	if not topEntry then return end

	local userId = topEntry:GetAttribute("UserId")
	if not userId then return end

	local userDesc
	local success = pcall(function()
		userDesc = Players:GetHumanoidDescriptionFromUserId(userId)
	end)

	if not success or not userDesc then return end

	local displayName = Players:GetNameFromUserIdAsync(userId)
	local newRig = Players:CreateHumanoidModelFromUserId(userId)
	if not newRig then return end

	newRig.Name = rig.Name
	newRig.Parent = rig.Parent
	newRig:SetPrimaryPartCFrame(rig:GetPrimaryPartCFrame())
	rig:Destroy()

	-- Optional Scaling
	pcall(function()
		userDesc.HeadScale = 4.4
		userDesc.DepthScale = 4.4
		userDesc.WidthScale = 4.4
		userDesc.HeightScale = 4.4
		userDesc.BodyDepthScale = 4.4
		userDesc.BodyHeightScale = 4.4
		userDesc.BodyWidthScale = 4.4
	end)

	local humanoid = newRig:FindFirstChildOfClass("Humanoid")
	if humanoid then
		pcall(function()
			humanoid:ApplyDescription(userDesc)
		end)
		humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.None
		humanoid.PlatformStand = true
	end

	local root = newRig:FindFirstChild("HumanoidRootPart")
	if root then
		root.Anchored = true
		local originalCFrame = root.CFrame
		RunService.Heartbeat:Connect(function()
			if root and root.Parent then
				root.CFrame = originalCFrame
			end
		end)
	end

	local animator = humanoid and humanoid:FindFirstChildWhichIsA("Animator")
	if not animator and humanoid then
		animator = Instance.new("Animator")
		animator.Parent = humanoid
	end

	if animator then
		local anim = Instance.new("Animation")
		anim.AnimationId = DANCE_ANIM_IDS[math.random(1, #DANCE_ANIM_IDS)]
		local track = animator:LoadAnimation(anim)
		track.Looped = true
		track:Play()
	end

	attachBillboardToRig(newRig, displayName, statName)
end

local function updateAllRigs()
	for statName, rigName in pairs(STAT_TO_POSITION_NAME) do
		local rig = TopPositionsFolder:FindFirstChild(rigName)
		if rig then
			applyTopPlayerToRig(statName, rig)
		end
	end
end

-- Delay initial update a bit longer to ensure LeaderboardData is populated
task.wait(10)
updateAllRigs()

while true do
	task.wait(UPDATE_INTERVAL)
	updateAllRigs()
end

Honestly, I’m not sure what this issue is, cause it seems like a new rig is created regardless of whether or not the top player is the same (assuming there are no errors of course). That should prevent the animation track limit from being reached, since your accessing a new animator. The run service connection may be preventing the rig from being fully destroyed (not 100% sure) and causing a memory leak (you should probably fix that), but since you are accessing a new rig each time, it shouldn’t really matter. The only thing I can think of is that somehow the rig inputted as a parameter ends up being the rig that is animated. Don’t know how this would happen but that’s all I can think of. Maybe the issue is present elsewhere? Sorry I couldn’t be of much help lol.

No worries!

I change the update timer to 10 minutes to prevent this issue from having such a massive effect.

Otherwise, I image my emote GUI is causing some of the issue as well?

Full Script:

Summary
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local EmoteModule = require(ReplicatedStorage.Modules:WaitForChild("EmoteModule"))
local remote = ReplicatedStorage.RemoteEvents:WaitForChild("PlayEmote")
local Players = game:GetService("Players")

-- Store current emote animation per player
local activeEmotes = {}

-- Clean up when players leave
Players.PlayerRemoving:Connect(function(player)
	activeEmotes[player] = nil
end)

remote.OnServerEvent:Connect(function(player, emoteName)
	local character = player.Character
	if not character then return end

	local humanoid = character:FindFirstChildWhichIsA("Humanoid")
	if not humanoid then return end

	-- Stop any existing emote track
	if activeEmotes[player] then
		activeEmotes[player]:Stop()
		activeEmotes[player] = nil
	end

	-- Stop command, just exit
	if emoteName == "Stop" then return end

	local animId = EmoteModule[emoteName]
	if not animId then return end

	local animation = Instance.new("Animation")
	animation.AnimationId = animId
	local track = humanoid:LoadAnimation(animation)
	track:Play()

	-- Store the playing track
	activeEmotes[player] = track

	-- Listen for jump and stop if triggered
	local connection
	connection = humanoid.StateChanged:Connect(function(_, newState)
		if newState == Enum.HumanoidStateType.Jumping or Enum.HumanoidStateType.Freefall then
			if activeEmotes[player] then
				activeEmotes[player]:Stop()
				activeEmotes[player] = nil

				-- NEW: Tell client the emote stopped
				local emoteStopped = ReplicatedStorage.RemoteEvents:FindFirstChild("EmoteStopped")
				if emoteStopped then
					emoteStopped:FireClient(player)
				end
			end
			if connection then
				connection:Disconnect()
			end
		end

	end)
end)

Within this script a new animation is created each time a player selected an emote, what would be a better way of working this system?

    local animId = EmoteModule[emoteName]
	if not animId then return end

	local animation = Instance.new("Animation")
	animation.AnimationId = animId
	local track = humanoid:LoadAnimation(animation)
	track:Play()

I would recommend that you destroy the tracks before you clear the reference to them, since it doesn’t actually destroy the track and just leaves it to be collected by the garbage collector, which you probably shouldn’t be relying on.

The problem is repeatedly loading a new Animation instance each time. You should create it once, then store the reference to it if it needs to be played again.