Summary
In UE 5.7 (regression from 5.5), the editor permanently hangs at Initializing world 84% when loading a level that has baked lighting data, if the World Settings panel is open. The game thread deadlocks against itself on the non-recursive UActorComponent::AllUCSModifiedPropertiesLock SRW lock.
The World Settings “Lightmaps” list (FLightmapCustomNodeBuilder) serializes the entire level via FFindLightmapsArchive to enumerate lightmap textures. That walk re-enters component serialization through a UChildActorComponent → StaticDuplicateObject, which requests the lock as write while the outer component still holds it as read. Windows SRW locks are not recursive or upgradeable, so the thread blocks forever (0% CPU, pinned memory, no window, no log output).
The hang only occurs when the level has built lighting data, because FFindLightmapsArchive early-outs when no lightmap textures are loaded.
What Type of Bug are you experiencing?
Rendering (Graphics / Niagara)
Steps to Reproduce
- Use a project with static lighting enabled (
r.AllowStaticLighting=True). A forward-shaded/VR config reproduces it readily, but the bug is renderer-agnostic. - Create a level that contains at least one actor with a
UChildActorComponent(e.g. a Blueprint actor with a Child Actor Component), alongside normal static meshes set to Static mobility. - Build lighting (GPU Lightmass or Lightmass) so the level produces baked lightmap data (a
*_BuiltData.uasset). Save. - Make sure the World Settings tab is open (so the editor restores it the next time the map loads).
- Reload the level — or set it as the editor startup map and restart the editor.
- Observe the editor hang at
Initializing world 84%.
Note: deleting the level’s *_BuiltData.uasset makes the level load normally, which isolates the trigger to baked lighting data being present.
Expected Result
The level loads, and the World Settings “Lightmaps” section populates with the baked lightmap textures.
Observed Result
The game thread deadlocks and the editor hangs forever at Initializing world 84%:
- Process alive but 0% CPU, 0% disk, memory pinned, no editor window, no error, no further log lines.
- As the startup map: the splash screen appears, disappears, and the editor never opens.
- Mid-session: freezes at 84%.
Affects Versions
5.7
Platform(s)
Windows
For crash reports, include your callstack
Symbolized game-thread call stack (condensed):
ntdll!RtlAcquireSRWLockExclusive
UE::FWindowsSharedMutex::Lock() WindowsPlatformMutex.h:82
UE::TRWScopeLock<FPlatformRWLock>::ctor(SLT_Write) ScopeRWLock.h:169
UActorComponent::Serialize() ActorComponent.cpp:3267 <-- WRITE lock requested here
USceneComponent::Serialize() / UPrimitiveComponent::Serialize()
StaticDuplicateObjectEx() / StaticDuplicateObject() UObjectGlobals.cpp:3269 / 3116
UChildActorComponent::Serialize() ChildActorComponent.cpp:183 (duplicates child-actor template)
FFindLightmapsArchive::operator<<(UObject*&) World.cpp:9641
... (recursive serialization of the level: actors, components,
Blueprints, BlueprintGeneratedClasses, EdGraphs, K2Nodes, pins) ...
UActorComponent::Serialize() ActorComponent.cpp:3282 <-- READ lock already held here
(mid-serialize of UCSModifiedProperties, SLT_ReadOnly taken at line 3279)
ULevel::Serialize() Level.cpp:755
FFindLightmapsArchive::FFindLightmapsArchive() World.cpp:9619
UWorld::GetLightMapsAndShadowMaps() World.cpp:9682
FLightmapCustomNodeBuilder::RefreshLightmapItems() WorldSettingsDetails.cpp:519
FLightmapCustomNodeBuilder::GenerateChildContent() WorldSettingsDetails.cpp:343
... SDetailsView::SetObject(WorldSettings) ...
SLevelEditor::RestoreContentArea() (restores the saved World Settings tab on startup)
EditorInit() -> GuardedMain()
The deadlock: ActorComponent.cpp:3279 takes the static AllUCSModifiedPropertiesLock as SLT_ReadOnly; while that read scope is still active (mid-serialize at line 3282), the reference walk re-enters component serialization through UChildActorComponent → StaticDuplicateObject, and ActorComponent.cpp:3267 requests the same lock as SLT_Write. Non-recursive SRW lock + same thread holding read then requesting write = self-deadlock.
Why it tracks the presence of built data — FFindLightmapsArchive early-outs unless lightmap texture objects are loaded (World.cpp:9606-9620):
GetObjectsOfClass(ULightMapTexture2D::StaticClass(), Objects);
GetObjectsOfClass(UShadowMapTexture2D::StaticClass(), Objects);
GetObjectsOfClass(ULightMapVirtualTexture2D::StaticClass(), Objects);
if (Objects.Num()) // only walks the level when lightmaps exist
{
*this << InSearch; // <-- the walk that self-deadlocks
}
No built data → no lightmap textures → walk skipped → loads fine. Built data present (any size) → walk runs → deadlock.
Additional Notes
All three required to trigger:
- A level with baked lighting (built data present).
- Level content that references a Blueprint /
UChildActorComponent(so the collector walk re-enters component serialization viaStaticDuplicateObject). - The World Settings panel open/restored (so
RefreshLightmapItemsruns). On startup this happens automatically when the World Settings tab is saved as open.
Reproduced on stock 5.7 — independent of any third-party plugin or engine patch. Independent of built-data size (a 140 MB bake hangs the same as 1.3 GB). Independent of Virtual Texture lightmaps, ray tracing / “Support Hardware Ray Tracing”, and PSO precaching (all toggled, all still hang).
Workaround (project-side): prevent the World Settings tab from spawning at startup so the Lightmaps list never builds. In the per-user editor layout …/AppData/Local/UnrealEngine/Editor/EditorLayout.json, set the WorldSettingsTab entry from "TabState": "OpenedTab" to "TabState": "ClosedTab". After that the baked level loads normally. Caveat: manually opening Window → World Settings on a map that has built data re-triggers the identical hang; keep it closed on baked maps, or open it only on maps without built data. Re-baking does not require the panel (use the toolbar Build ▸ Build Lighting Only).
Suggested engine fix: have FFindLightmapsArchive::operator<< skip UBlueprint / UBlueprintGeneratedClass / UChildActorComponent references (the collector only needs lightmap textures, which never live in Blueprint graphs), or make the AllUCSModifiedPropertiesLock usage reentrancy-safe so a read holder can take the write path without deadlocking.