Hello!
I’m having an issue with specific blueprint class hierarchy and setup: two blueprint actor classes where one of them is derived from the other, two blueprint components where one of them is derived from the other, base component class overrides component class in base actor, derived component class overrides component class in derived actor (see steps to reproduce).
The crash happens when loading such object in packaged build on Async Loading Thread. This means that most scenarios of loading will crash, i.e. calling LoadAsync, LoadSynchronous (this also uses ALT), placing actor on level and loading the level etc.
Provided steps can be reproduced on different base classes, e.g. NiagaraActor. I think it’s reproducible using any native base class that have a native component property created in a class constructor. NiagaraActor or StaticMesh actor crashes in this specific place related to UPrimitiveComponent::BeginDestroy but if the component is not derived from UPrimitiveComponent the game will still crash, but in different place.
This crash happens also in Launcher/Perforce 5.6.1 as well as Perforce //UE5/Main build, last checked on 12/15/2025.
This crash is stopping my team of using desired class hierarchies. It causes hard to predict crashes in packaged build without any warning in editor time.
While debugging I’ve observed that during child blueprint actor loading on AsyncLoadingThread, after finishing CDO construction the system attempts to instantiate CDO’s subobject again with InstantiateSubobjects in FObjectInitializer::PostConstructInit. This leads to reconstruction of the previously constructed component (among others). Reconstructing involves destroying previous instance of the component object. This operation seems to be forbidden on Async Loading Thread - this conclusion is being drawn from multiple places in code:
- hitting IsGameThread() ensure “GC lock can only be acquired on the game thread.” in StaticAllocateObject
- hitting IsGameThread() check in DetachFence.BeginFence() in PrimitiveComponent::BeginDestroy
- hitting IsGameThread() check in GUObjectArray.FreeUObjectIndex(Obj) in StaticAllocateObject
The crashes are directly caused but one of the above assertions.
Is this a known issue? Can I expect a fix for it in forseable future? If there would be a cherrypick CL fix I could introduce to our engine I would appreciate it, as well as any other help.
[Attachment Removed]