In short
SetNetworkOwner and SetNetworkOwnershipAuto only work on parts that physics can move. The part you called it on is anchored, or joined by a weld or a Motor6D to a part that is, and the server always owns anchored parts. Unanchor every part of the model first (car templates are often stored anchored), remove welds to the map, then set the owner. Call part:CanSetNetworkOwnership() first when you are not sure: it returns false and the reason instead of erroring.
What the message means
ServerScriptService.CarSpawner:14: Network Ownership API cannot be called on Anchored parts or parts welded to Anchored parts.
Other forms of the same message:
Network Ownership API can only be called from the Server.Can only call Network Ownership API on a part that is descendent of Workspace
Network ownership decides which computer simulates a part's physics: the server, or one player's client. Roblox applies it to a whole assembly, the group of parts held together by welds and other rigid joints. If any part of that assembly is anchored, nothing in it moves, the server owns all of it, and the ownership calls refuse to change that.
Two related messages come from the same API. Network Ownership API can only be called from the Server. means a LocalScript called it. Can only call Network Ownership API on a part that is descendent of Workspace means the part is not in the Workspace yet, for example a clone you have not parented.
Causes and fixes
Two things cause this error in practice. Each one below has the smallest code that triggers it, then the fix.
The part is still anchored when the owner is set
Templates in ServerStorage are often anchored so they do not fall when you place them. A spawner that clones the model and sets the owner straight away hits the anchored parts.
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local template = ServerStorage:WaitForChild("Car") :: Model
local function spawnCar(player: Player)
local car = template:Clone()
car.Parent = workspace
local seat = car:FindFirstChildWhichIsA("VehicleSeat", true)
if seat then
-- the template is anchored: Network Ownership API cannot be called on Anchored parts...
seat:SetNetworkOwner(player)
end
end
Players.PlayerAdded:Connect(spawnCar)
Unanchor every part of the model after you place it, then check CanSetNetworkOwnership and set the owner.
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
local template = ServerStorage:WaitForChild("Car") :: Model
local function spawnCar(player: Player)
local car = template:Clone()
car.Parent = workspace
for _, part in car:GetDescendants() do
if part:IsA("BasePart") then
part.Anchored = false
end
end
local seat = car:FindFirstChildWhichIsA("VehicleSeat", true)
if seat then
local ok, reason = seat:CanSetNetworkOwnership()
if ok then
seat:SetNetworkOwner(player)
else
warn("[CarSpawner] cannot set owner:", reason)
end
end
end
Players.PlayerAdded:Connect(spawnCar)
The part is welded to something anchored
The part itself is unanchored, but a WeldConstraint, Weld or Motor6D joins it to an anchored part: the map, a building, or one anchored decoration inside the same model. That makes it part of an anchored assembly.
local Players = game:GetService("Players")
local crate = workspace:WaitForChild("Crate") :: BasePart
-- the crate is welded to the anchored dock it sits on
local weld = Instance.new("WeldConstraint")
weld.Part0 = crate
weld.Part1 = workspace:WaitForChild("Dock") :: BasePart
weld.Parent = crate
Players.PlayerAdded:Connect(function(player)
-- Network Ownership API cannot be called on ... parts welded to Anchored parts.
crate:SetNetworkOwner(player)
end)
Remove or disable the weld to the anchored part before you hand the part to a player. To find hidden joints, loop over part:GetJoints() in a script and print what each one connects.
local Players = game:GetService("Players")
local crate = workspace:WaitForChild("Crate") :: BasePart
local function freeFromAnchored(part: BasePart)
for _, joint in part:GetJoints() do
if joint:IsA("WeldConstraint") then
local other = if joint.Part0 == part then joint.Part1 else joint.Part0
if other and other.Anchored then
joint.Enabled = false
end
end
end
end
Players.PlayerAdded:Connect(function(player: Player)
freeFromAnchored(crate)
if crate:CanSetNetworkOwnership() then
crate:SetNetworkOwner(player)
end
end)
This example only handles WeldConstraint. Classic Weld and Motor6D joints use Part0 and Part1 too; check those the same way if your model uses them.
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.
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
- Open Output (Window menu, or the Script tab), clear it with Ctrl+K (⌘K on Mac), and press Play.
- Find the first red line. It starts with the script's place in the Explorer and the line number, such as
ServerScriptService.Shop:12:. - Click the red line. Studio opens that script with the cursor on the failing line.
- Read the lines between
Stack BeginandStack Endunder it: they list the calls that led there, newest first, so you can see which function called the broken one. - Still not sure which value is wrong? Add
print(typeof(x), x)just above the line, or set a breakpoint on it and read the values in the Watch window.
Questions
Do anchored parts need network ownership?
No. Anchored parts never move by physics, and the server always owns them. Only set an owner for unanchored parts that a player drives, carries or pushes.
How do I see who owns a part?
In Studio, turn on Network owners in the viewport visualization options while you test. In a server script, part:GetNetworkOwner() returns the owning Player, or nil when the server owns it.
Why does it work once and then fail?
Something anchored the part or welded it to an anchored part after the first call, such as a script that parks the car or a build tool that welds it in place. Call CanSetNetworkOwnership() before each SetNetworkOwner and log the reason it returns.
Can RoCode fix it?
Yes. Paste the Output line into RoCode. It reads the scripts and the model in the place you have open, finds the anchored part or weld and changes the spawner to unanchor and check before it sets the owner.
Sources and further reading
- Roblox Creator Docs: network ownership. the server always owns anchored parts; ownership applies per assembly
- Roblox Creator Docs: BasePart:CanSetNetworkOwnership
- Roblox Creator Docs: assemblies
How the code was checked: every block marked Fixed passes Luau's strict type checker against Roblox's API definitions (luau-lsp, 4 November 2026), and every block marked Breaks compiles and fails only when it runs. The message wording, and the two related messages, were checked against the message strings in Roblox Studio itself (macOS build installed on 24 October 2026) on 4 November 2026. The ownership rules are from the network ownership page in the Roblox creator docs. A type check catches misspelt APIs and wrong types, not game logic, so playtest in Studio before you publish.