Bug: MeshPart/UnionOperation fails to sync on reconnect - "URL too long" error
Summary
When reconnecting Rojo for initial synchronization, MeshPart and UnionOperation instances are created without their mesh data (MeshId/MeshContent is empty). This is caused by two issues:
- Roblox behavior change:
Instance.new("MeshPart")now succeeds instead of failing, creating an empty MeshPart - URL length limit: The fallback mechanism fails with "URL too long" when serializing many instances
Environment
- Rojo version: 7.6.x?
- Roblox Studio: Latest (as of November 2025)
- OS: Windows 11
Root Cause Analysis
Issue 1: Instance.new("MeshPart") behavior changed
The current code in plugin/src/Reconciler/reify.lua assumes Instance.new("MeshPart") will fail:
local createSuccess, instance = pcall(Instance.new, virtualInstance.ClassName)
if not createSuccess then
-- Mark this instance and all its children as unapplied
-- The fallback sync mechanism will handle it
addAllToPatch(unappliedPatch, virtualInstances, id)
return
end
Expected behavior: Instance.new("MeshPart") fails → instance goes to fallback → SerializationService creates proper MeshPart with mesh data
Actual behavior: Instance.new("MeshPart") succeeds → creates empty MeshPart → attempts to set MeshContent property → fails because MeshContent is read-only after creation
Debug output showing the issue:
[MESHDBG] reify: Instance.new('MeshPart') for id= 5ef5631551f6a828dc02e4daa5df4001 name= Ball
[MESHDBG] reify: createSuccess= true instance= Ball
...
[MESHDBG] reify: setProperty MeshPart . MeshContent = Content success= false ← FAILS!
Issue 2: Fallback fails with "URL too long"
Even though the instance ends up in the unapplied patch (due to failed properties), the fallback mechanism in ServeSession:__replaceInstances() fails when there are many instances because all instance IDs are passed in the URL:
[MESHDBG] __replaceInstances: calling serialize API with 1983 ids (includes Ball)
[MESHDBG] __replaceInstances: serialize API ERROR: Unknown HTTP error: URL too long
The serialize API endpoint puts all IDs in the URL query string, which exceeds the HTTP URL length limit (~2000 characters) when there are many instances.
Steps to Reproduce
- Create a Rojo project with MeshPart instances that have MeshId/MeshContent set
- Start Rojo serve and connect from Studio
- Disconnect Rojo
- Reconnect Rojo
- Observe that MeshPart instances have empty MeshId
Expected Behavior
MeshPart instances should retain their MeshId/MeshContent after reconnecting.
Actual Behavior
MeshPart instances are created with empty MeshId because:
Instance.new("MeshPart")succeeds (creating empty mesh)MeshContentcannot be set (read-only)- Fallback mechanism fails due to URL length
Proposed Fix
Fix 1: Force MeshPart/UnionOperation to always use fallback
In reify.lua, force these classes to go through the fallback mechanism even if Instance.new succeeds:
local createSuccess, instance = pcall(Instance.new, virtualInstance.ClassName)
-- Force fallback for classes that require SerializationService
local requiresFallback = virtualInstance.ClassName == "MeshPart"
or virtualInstance.ClassName == "UnionOperation"
if not createSuccess or requiresFallback then
addAllToPatch(unappliedPatch, virtualInstances, id)
return
end
Debug Output (Full Trace)
Note: [MESHDBG] prefix is from debug prints we added during investigation to trace the issue.
[MESHDBG] diff: MARK ADDED MeshPart id= 5ef5631551f6a828dc02e4daa5df4001 name= Ball
[MESHDBG] reify: Instance.new('MeshPart') for id= 5ef5631551f6a828dc02e4daa5df4001 name= Ball
[MESHDBG] reify: createSuccess= true instance= Ball
[MESHDBG] reify: setProperty MeshPart . MeshContent = Content success= false
[MESHDBG] reify: UNAPPLIED PROPERTIES for MeshPart id= 5ef5631551f6a828dc02e4daa5df4001
[MESHDBG] applyPatch: Processing ADDED MeshPart id= 5ef5631551f6a828dc02e4daa5df4001 name= Ball
[MESHDBG] applyPatch: SKIP MeshPart id= 5ef5631551f6a828dc02e4daa5df4001 - already exists in instanceMap
[MESHDBG] ServeSession __initialSync: unapplied UPDATE id= 5ef5631551f6a828dc02e4daa5df4001 name= Ball
[MESHDBG] __replaceInstances: calling serialize API with 1983 ids (includes Ball)
[MESHDBG] __replaceInstances: serialize API ERROR: Unknown HTTP error: URL too long
After applying batching fix:
Debug output after implementing the batching solution:
[MESHDBG] __replaceInstances: processing 1983 ids in batches of 50 (includes Ball)
[MESHDBG] __replaceInstances: Ball is in batch 7 with 50 ids
[MESHDBG] __replaceInstances: deserialized Ball, class= MeshPart MeshId= rbxassetid://554089739
[MESHDBG] __replaceInstances: after all batches, modelSuccess= true total replacements= 1983
[MESHDBG] __replaceInstances: replacing Ball
[MESHDBG] oldInstance= ...Ball oldMeshId= ← Empty before fix
[MESHDBG] replacement class= MeshPart newMeshId= rbxassetid://554089739 ← Correct after fix
[MESHDBG] __replaceInstances: DONE - Ball final state: MeshId= rbxassetid://554089739
Related Files
plugin/src/Reconciler/reify.lua- Instance creation logicplugin/src/Reconciler/applyPatch.lua- Patch applicationplugin/src/ServeSession.lua- Fallback mechanism (__replaceInstances)src/web/api.rs- Server-side serialize endpoint
Additional Context
This bug affects any project with MeshPart or UnionOperation instances. The issue became apparent after a Roblox update that changed the behavior of Instance.new("MeshPart") from failing to succeeding.
Could there be a better solution?
I just confirmed the official Rojo codebase does have the same issues described in the bug report.
Simple repro:
- Create a Rojo project with a .rbxm file in the
Workspace, do not sync yet. Let's say aRig - now, do the initial sync. It will load the
Rigwith many MeshParts but no MeshId.