Please help. I can't resolve this error

Hi. I’m trying to fix this mistake but I couldn’t until now. I was able to isolate the error to these two scripts:

-- Script
local ReplicatedSorage = game:GetService("ReplicatedStorage")

local sourceFolder = Instance.new("Folder", ReplicatedSorage)
sourceFolder.Name = "Source"

local part
while true do
	for _ = 1, 10 do
		part = Instance.new("Part", sourceFolder)
	end
	wait(5)
	sourceFolder:ClearAllChildren()
end

-- LocalScript
local ReplicatedSorage = game:GetService("ReplicatedStorage")

local sourceFolder = ReplicatedSorage:WaitForChild("Source")

local targetFolder = Instance.new("Folder", workspace)
targetFolder.Name = "Target"

local onChildAdded = function (child)
	child.Parent = targetFolder
end

sourceFolder.ChildAdded:Connect(onChildAdded)

In short, the server dynamically creates parts in replicatedstorage every so often. Then the client moves each part to workspace. The error is this:

06:42:42.850 - Something unexpectedly tried to set the parent of Part to Target while trying to set the parent of Part. Current parent is Source. (x10)

On the client side the parts don’t move to workspace.

I remember that some time ago I did something similar and it worked well.

Seems like you’re changing the parent too fast, add a wait() before doing it again.

Wow, it worked! But there is some more detailed explanation in case I make this mistake in other contexts.

What do you mean?

I mean, when is it too fast to do something on the client? I understand that you have to wait for the parts to replicate but in this case childadded does that job.

Here’s more info about it: Remove the " Something unexpectedly tried to set the parent of X to NULL while trying to set the parent of X" - #31 by Maximum_ADHD

This is how Roblox instances work at the moment. You can’t destroy/reparent parts instantly after they have been reparented and you will get that error message. You can go around it by waiting the smallest possible amount, which wait() will do, but the wait function will also wait to long (around 0.03 seconds which is longer than what you need to wait). This code should also go around your issue:

local onChildAdded = function (child)
	spawn(function() child.Parent = targetFolder end)
end

For all other cases (even this one) I would recommend verifying that your use-case actually requires the behaviour you’re defining here.

1 Like

and make RunService.Stepped:wait() work too? or is it a lot like wait().

It might be “better” than just doing wait(), but it’s still a time-based wait, while using spawn() ensures it gets executed as fast as possible while still giving the Roblox thread enough time to process the instance reparenting.

Then I’ll use spawn(). Thank you so much for helping me.

The .RenderStepped event of RunService is the fastest option.

1 Like
local t = tick()
game:GetService("RunService").RenderStepped:Wait()
print("Time passed RenderStepped: " .. tick()-t)

local t = tick()
spawn(function() end)
print("Time passed spawn: " .. tick()-t)

Time passed RenderStepped: 0.07803201675415
Time passed spawn: 8.8214874267578e-06

Additionally, a lagging client will stretch the RenderStepped event as long as they want.

Putting a Wait method on a connection (RBXScriptSignal) like RenderStepped or Touched, it’ll make the thread yield until the event fires and returns its parameters /arguments. If you add a Wait method to a RenderStepped, it’ll make the script yield until the event is fired, so RenderStepped doesn’t always run at 60 Hz, – its frequency is dependent on your frame rate since it relies on the connection itself to fire, which has its frequency dependent on the machine’s frame rate

It doesn’t matter what you use, but I prefer this method.