Crash when loading Blueprint actor

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]

Steps to Reproduce

  1. Create Blueprint actor class derived from StaticMeshActor class, let’s call it BP_StaticMeshActor.
  2. Create Blueprint actor class derived from BP_StaticMeshActor from step 1, let’s call it BP_StaticMeshActor_Child.
  3. Create Blueprint component class derived from StaticMeshComponent, let’s call it BP_StaticMeshComponent.
  4. Create Blueprint component class derived from BP_StaticMeshComponent, let’s call it BP_StaticMeshComponent_Child.
  5. Inside BP_StaticMeshActor, set BP_StaticMeshComponent class as a Static Mesh Component’s Class Override.
  6. Inside BP_StaticMeshActor_Child, set BP_StaticMeshComponent_Child class as a Static Mesh Component’s Class Override.
  7. Put BP_StaticMeshActor_Child on a level.
  8. Set this level as a game default map, so that it’s startup map in packaged build.
  9. Package the game and run the packaged build.
  10. Observe the game crashes.

[Attachment Removed]

Hey there, we appreciate that you’ve taken the time to isolate the repro and prepare those repro steps. I can confirm that following these steps I’m also getting the same failing ensure in a packaged build. Object destruction on the AsyncLoadingThread is unexpected, so I’ve created UE-358685.

My guess is, a workaround could be to modify FObjectInstancingGraph::GetInstancedSubobject() to try to find, and then rename, an existing object with a different class out of the way before attempting to construct it again. Though the safer bet would be to wait until an engineer has addressed UE-358685.

[Attachment Removed]