Roblox Studio error

Maximum event re-entrancy depth exceeded

What Maximum event re-entrancy depth exceeded means in Roblox Studio, the three things that cause it with the code that triggers each, and the fix for each one.

Updated 23 October 20263 min readErrorLuau

In short

An event handler triggered its own event. For example, a Changed handler that changes the value it watches fires Changed again, which runs the handler again, and so on. Roblox stops the chain after a fixed depth and prints this, naming the object class and the event (IntValue.Changed). Make the handler leave the value alone when it is already right, or change it somewhere the event does not watch.

On this page
  1. What it means
  2. Causes and fixes
  3. Fix it with RoCode
  4. Find the line
  5. Questions
  6. Sources

What the message means

Output (example)
Maximum event re-entrancy depth exceeded for IntValue.Changed

Other forms of the same message:

  • Maximum event re-entrancy depth exceeded for Humanoid.HealthChanged

Re-entrancy means an event firing again while its own handler is still running. A little is normal; endless re-entry is a bug, and Roblox cuts it off instead of letting it freeze the game.

The message names the event, not your script. Search your scripts for handlers on that event (for example .Changed:Connect) that also set the property it watches.

Causes and fixes

Three things cause this error in practice. Each one below has the smallest code that triggers it, then the fix.

A Changed handler changes the same value

A bonus that adds to a value from inside that value's own Changed handler is the classic case. Every change fires Changed again, which adds again.

Breaks Script in ServerScriptService named CoinBonus
local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)
	local coins = player:WaitForChild("leaderstats"):WaitForChild("Coins")
	coins.Changed:Connect(function()
		-- a "bonus coin" on every change fires Changed again, forever
		coins.Value += 1
	end)
end)

Apply the change where the value is set in the first place, in one function every script calls, instead of reacting to it.

Fixed Script in ServerScriptService named CoinBonus
local BONUS = 1

local function addCoins(coins: IntValue, amount: number)
	coins.Value += amount + BONUS
end

local coins = Instance.new("IntValue")
addCoins(coins, 10)
print(coins.Value) -- 11

Clamping inside Changed (if value > MAX then coins.Value = MAX end) is safe, because the second set does not change the value again, so the chain stops after one step.

A Text handler rewrites the Text it listens to

Formatting a TextBox as the player types, by setting Text inside its own GetPropertyChangedSignal("Text") handler, fires the handler again with the new text. If the formatting always adds something, it never settles.

Breaks LocalScript in a TextBox in StarterGui named PriceBox
local box = script.Parent

box:GetPropertyChangedSignal("Text"):Connect(function()
	-- adds "$" every time, which changes Text again, forever
	box.Text = "$" .. box.Text
end)

Only set Text when the formatted text is different from what is already there, so the second round changes nothing and the chain ends.

Fixed LocalScript in a TextBox in StarterGui named PriceBox
local box = script.Parent :: TextBox

box:GetPropertyChangedSignal("Text"):Connect(function()
	local digits = box.Text:gsub("%D", "")
	local formatted = "$" .. digits
	if box.Text ~= formatted then
		box.Text = formatted
	end
end)

Two handlers keep changing each other

A handler on A sets B, and a handler on B sets A, for example two values kept in sync with a conversion that never settles. Neither looks wrong on its own.

Breaks Script in ServerScriptService named Sync
local celsius = Instance.new("NumberValue")
local fahrenheit = Instance.new("NumberValue")

celsius.Changed:Connect(function(c)
	fahrenheit.Value = c * 9 / 5 + 32
end)
fahrenheit.Changed:Connect(function(f)
	-- adds 0.1 each round, so the values never settle
	celsius.Value = (f - 32) * 5 / 9 + 0.1
end)

celsius.Value = 20

Keep one source of truth and compute the other from it, in one direction only.

Fixed Script in ServerScriptService named Sync
local celsius = Instance.new("NumberValue")
local fahrenheit = Instance.new("NumberValue")

-- celsius is the source; fahrenheit only follows it
celsius.Changed:Connect(function(c: number)
	fahrenheit.Value = c * 9 / 5 + 32
end)

celsius.Value = 20
print(fahrenheit.Value) -- 68

Fix it in your place

Paste the error, RoCode fixes it in your place

Copy the line from Output and paste it here. RoCode opens the script it names in the place you have open in Studio, works out which of the causes above it is, and edits the code there instead of handing you a snippet to paste.

For example: Maximum event re-entrancy depth exceeded for IntValue.Changed

RoCode is an AI agent for Roblox Studio: it reads the scripts in the place you have open, finds the line and edits it there, and every change is an undo point. It runs on Windows or macOS with a desktop browser. Free to start, with free credits every day.

How to find the line that causes it

  1. The message names the class and event, for example IntValue.Changed. Search all scripts (Ctrl+Shift+F) for that event, such as .Changed:Connect or HealthChanged.
  2. In each handler you find, look for a line that sets the property the event watches.
  3. Recent Studio builds can add the function and line it was calling to the message; if yours does, start there.

Questions

What is the re-entrancy depth?

How many times an event can fire again from inside its own handlers before Roblox stops it. Normal code never comes near it; reaching it means a loop.

Does setting a value to the same value fire Changed?

For value objects such as IntValue, no: Changed fires when the value actually changes. That is why setting it only when it is wrong ends the loop.

Is this the same as stack overflow?

They are cousins. Stack overflow is a function calling itself; this is an event setting itself off. The fix is the same idea: give the repeat a way to stop.

Can RoCode fix it?

Yes. Paste the Output line into RoCode. It searches the scripts in your open place for the handler that sets off its own event and rewrites it.

Sources and further reading

How the code was checked: every block marked Fixed passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 23 October 2026), and every block marked Breaks compiles and fails only when it runs. The message wording was checked against the message format strings in Roblox Studio itself (macOS build of 13 October 2026) on 23 October 2026; recent builds can also name the function and line it was calling. A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.

Stop hunting errors line by line.

RoCode reads the scripts in your open place, fixes the error where it happens and tells you what it changed. Free every day, no card required.