Description

Geometry Collection cluster handles leaking and causing ensures with field systems.
The licensee has shared their analysis:

We have been tracking down an assert that seems to happen occasionally when playing in FPBDRigidsSolver::BufferPhysicsResults, seemingly because the IPhysicsProxyBase* we get out from the handle during iteration has already been deleted.
After some debugging it seems these handles that still remain are always the ones created in FRigidClustering::CreateClustersFromNewIslands. These handles also seem to remain in FPBDRigidsSOAs::ClusteredParticles forever (even after unloading the relevant geometry collection actors), and the array keeps getting more and more invalid handles where the PhysicsProxy has already been deleted.
It seems that a field system we have that sets GCs to dynamic occasionally picks up one of these handles, and if the state wasn't already marked as dynamic it gets included in the next FPBDRigidsSolver::BufferPhysicsResults, which then tries to read from the already freed memory PhysicsProxy.
I have set up a test project which seems to be able to reproduce the assert easily (included a video). In this case I ran the engine with -poisonmallocproxy to help trigger the assert and circumvent the logic reading old "valid" data in memory that could still be committed.
To simulate the actor unloading (in reality going outside streaming range) I have tagged it with a Data Layer and manually ran wp.Runtime.SetDataLayerRuntimeState Unloaded DL_Test.

Although the licensee's setup environment reliably reproduces the crash, I've set this as MediumDefectProbability because it does not always crashes without the -poisonmallocproxy flag.
I've reproduced the behavior on 5.6 and 5.7 (CL44372627)

 

Steps to Reproduce

The licensee has provided a repro project. To use it:
Run the project with the -poisonmallocproxy flag;
Simulate-In-Editor;
Run the console command wp.Runtime.SetDataLayerRuntimeState Unloaded DL_Test;
Pull FS_MasterField2 towards the position the GC_Cube previously occupied;
Observe the crash.

To create the project from scratch:
Create a new blank project
Create a new OpenWorld level, save it (e.g. name: L_Test)
Add a cube
Select it, go to FractureMode (SHIFT+6)
Create a new GeometryCollection, default settings are fine, save
Fracture it (Uniform, Min and Max Voronoi Sites = 100 for more granularity)
Back to SelectionMode (SHIFT+1), select the GeometryCollectionActor, set ObjectType=Static
On the ContentBrowser, select the All folder and type FS_MasterField
Pull one to the scene
Set FieldActive=true, ActivationType=OnTick, FieldFalloffShape=Box, DelayAmount=0.0, and lastly AdvancedFieldSettings>ForceDynamicSwitching>ForceDynamicSwitching=true
Make it overlap half of the GC_Cube
Duplicate the field by selecting it and ALT+Dragging - move it away from GC_Cube
Select the GC_Cube and in the DataLayer window, Right-Mouse-Click, CreateNewDataLayerWithAsset>DataLayer, name it (e.g. DL_Test) and save it
Select DL_Test in the DataLayer window and set InitialRuntimeState=Activated
Save everything and close the engine
Open the project including the -poisonmallocproxy flag
Open L_Test
Simulate-In-Editor
The first field will break half the GC_Cube
Now Unload the rest of the GC_Cube by running the console command: wp.Runtime.SetDataLayerRuntimeState Unloaded DL_Test
Select the second field (FS_MasterField2) and pull it towards the position where the GC_Cube was
Observe the crash.

Callstack

Assertion failed: false [Link Removed] [Line: 2292]

UnrealEditor_Core!FDebug::CheckVerifyFailedImpl2() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Misc\AssertionMacros.cpp:728]
UnrealEditor_Chaos!Chaos::FPBDRigidsSolver::BufferPhysicsResults() [D:\build\++UE5\Sync\Engine\Source\Runtime\Experimental\Chaos\Private\PBDRigidsSolver.cpp:2292]
UnrealEditor_Chaos!Chaos::FPBDRigidsSolver::CompleteSceneSimulation() [D:\build\++UE5\Sync\Engine\Source\Runtime\Experimental\Chaos\Private\PBDRigidsSolver.cpp:2162]
UnrealEditor_Chaos!Chaos::AdvanceOneTimeStepTask::DoWork() [D:\build\++UE5\Sync\Engine\Source\Runtime\Experimental\Chaos\Private\PBDRigidsSolver.cpp:616]
UnrealEditor_Chaos!Chaos::FPBDRigidsSolver::AdvanceSolverBy() [D:\build\++UE5\Sync\Engine\Source\Runtime\Experimental\Chaos\Private\PBDRigidsSolver.cpp:1371]
UnrealEditor_Chaos!Chaos::FPhysicsSolverAdvanceTask::AdvanceSolver() [D:\build\++UE5\Sync\Engine\Source\Runtime\Experimental\Chaos\Private\Chaos\Framework\PhysicsSolverBase.cpp:180]
UnrealEditor_Chaos!Chaos::FPhysicsSolverAdvanceTask::DoTask() [D:\build\++UE5\Sync\Engine\Source\Runtime\Experimental\Chaos\Private\Chaos\Framework\PhysicsSolverBase.cpp:152]
UnrealEditor_Chaos!TGraphTask<Chaos::FPhysicsSolverAdvanceTask>::ExecuteTask() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Async\TaskGraphInterfaces.h:706]
UnrealEditor_Chaos!UE::Tasks::Private::FTaskBase::TryExecuteTask() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Tasks\TaskPrivate.h:527]
UnrealEditor_Chaos!LowLevelTasks::TTaskDelegate<LowLevelTasks::FTask * __ptr64 __cdecl(bool),48>::TTaskDelegateImpl<`LowLevelTasks::FTask::Init<`UE::Tasks::Private::FTaskBase::Init'::`2'::<lambda_1> >'::`13'::<lambda_1>,0>::CallAndMove() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Async\Fundamental\TaskDelegate.h:171]
UnrealEditor_Core!LowLevelTasks::FTask::ExecuteTask() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Public\Async\Fundamental\Task.h:627]
UnrealEditor_Core!LowLevelTasks::FScheduler::ExecuteTask() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Async\Fundamental\Scheduler.cpp:365]
UnrealEditor_Core!LowLevelTasks::FScheduler::WorkerLoop() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Async\Fundamental\Scheduler.cpp:724]
UnrealEditor_Core!`LowLevelTasks::FScheduler::CreateWorker'::`2'::<lambda_1>::operator()() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Async\Fundamental\Scheduler.cpp:188]
UnrealEditor_Core!FThreadImpl::Run() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\HAL\Thread.cpp:69]
UnrealEditor_Core!FRunnableThreadWin::Run() [D:\build\++UE5\Sync\Engine\Source\Runtime\Core\Private\Windows\WindowsRunnableThread.cpp:159]

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-315386 in the post.

0
Login to Vote

Unresolved
CreatedAug 26, 2025
UpdatedSep 11, 2025
View Jira Issue