When causing a C stack overflow by resuming coroutines recursively, the error message provides unhelpful stack trace information. The error message gives the stack trace of the thread being resumed, instead of giving the stack trace of the thread that actually resumed it.
Copy the following code and run it in the command bar (or in a LocalScript) in Studio:
local queuedThreads = {}
for _ = 1, 1000 do
task.spawn(function()
queuedThreads[#queuedThreads+1] = coroutine.running()
-- This is where the error says the problem is (Line 8).
coroutine.yield()
local nextThread = table.remove(queuedThreads)
-- This is where the problem actually is (Line 13).
task.spawn(nextThread)
end)
end
local initialThread = table.remove(queuedThreads)
task.spawn(initialThread)
(Note: Due to confusion in the replies, code has been edited for clarity about what itâs doing. Previously queuedThreads
was just called a
, which is what some of the replies are referring to.)
It gives the following output:
C stack overflow
Stack Begin
Script '[omitted for brevity]', Line 8
Stack End
C stack overflow (x6)
Maximum event re-entrancy depth exceeded for ScriptContext.ErrorDetailed
Which references Line 8 i.e. the line that calls coroutine.yield()
. This makes the programmer think that the issue is related to the call of coroutine.yield()
, but in fact that call is fine and completed successfully; the actual issue just happened to occur while the resumed thread was still sitting on that line.
It would be more helpful for the error message to provide the stack trace of the thread that did the resume i.e. Line 13âs task.spawn()
.
This particular example is trivial, but in more complex pieces of code where the coroutine.yield()
and task.spawn()
calls are separated in the source code it becomes harder to figure out what the issue is.