Random crash in DuplicateObject<USkeletalMesh>

We’re currently seeing a number of low-frequency crashes in our character customization system, specifically during skeletal mesh asset duplication operations. We duplicate meshes at runtime to generate retargeted or culled variants of individual meshes, but the duplication process would sometimes randomly crash during the serialization / deserialization of the duplicated object. We determined that this was related to a race condition where the RHI resources for the mesh were still being created on the render thread (as the mesh had just been loaded), which would cause the CPU data to be released (in FRenderResource::CreateRHIBuffer) while it was being read on the game thread by the duplication process. We tried to fix this by inserting an FRenderCommandFenceat the end of USkeletalMesh::InitResourcesfor the call to DuplicateObjectto wait upon, but while this greatly reduced the rate of crashes we’re still seeing intermittent issues with absurd amounts of memory being requested during the duplicate process such as Ran out of memory allocating 153248006144 (146148.7 MiB) bytes with alignment 65536 with the following stack trace:

FMemory::Realloc(void*, unsigned long long, unsigned int)+0x39 [Engine\Source/Runtime/Core/Public\HAL/FMemory.inl:121]
TSizedHeapAllocator<32, FMemory>::ForAnyElementType::ResizeAllocation(int, int, unsigned long long, unsigned int)+0x3d [Engine\Source/Runtime\Core\Public\Containers/ContainerAllocationPolicies.h:725]
TArray<FSpectatorReservation, TSizedDefaultAllocator<32>>::ResizeTo(int)+0x68 [Engine\Source/Runtime\Core\Public\Containers/Array.h:3143]
TSparseArray<TSetElement<TTuple<FName, FRuntimeSkinWeightProfileData>>, TSparseArrayAllocator<TSizedDefaultAllocator<32>, FDefaultBitArrayAllocator>>::Empty(int)+0x184 [Engine\Source/Runtime\Core\Public\Containers/Array.h:0]
FArchive& operator<< <TSetElement<TTuple<FName, FRuntimeSkinWeightProfileData>>, TSparseArrayAllocator<TSizedDefaultAllocator<32>, FDefaultBitArrayAllocator>>(FArchive&, TSparseArray<TSetElement<TTuple<FName, FRuntimeSkinWeightProfileData>>, TSparseArrayAllocator<TSizedDefaultAllocator<32>, FDefaultBitArrayAllocator>>&)+0x344 [Engine\Source/Runtime\Core\Public\Containers/SparseArray.h:1492]
FArchive& TSetPrivateFriend::Serialize<TTuple<FName, FRuntimeSkinWeightProfileData>, TDefaultMapHashableKeyFuncs<FName, FRuntimeSkinWeightProfileData, false>, FDefaultSetAllocator>(FArchive&, TSet<TTuple<FName, FRuntimeSkinWeightProfileData>, TDefaultMapHashableKeyFuncs<FName, FRuntimeSkinWeightProfileData, false>, FDefaultSetAllocator>&)+0x12 [Engine\Source/Runtime\Core\Public\Containers/Set.h:2204]
operator<< (FArchive&, FSkinWeightProfilesData&)+0x12 [Engine\Source/.\Runtime/Engine/Private/Animation/SkinWeightProfile.cpp:168]
FSkeletalMeshLODRenderData::SerializeStreamedData(FArchive&, USkinnedAsset*, int, unsigned char, bool, bool)+0x1d3 [Engine\Source/.\Runtime/Engine/Private/SkeletalMeshLODRenderData.cpp:800]
FSkeletalMeshLODRenderData::Serialize(FArchive&, UObject*, int)+0x4b1 [Engine\Source/.\Runtime/Engine/Private/SkeletalMeshLODRenderData.cpp:1020]
TIndirectArray<FSkeletalMeshLODRenderData, TSizedDefaultAllocator<32>>::Serialize(FArchive&, UObject*)+0x225 [Engine\Source/Runtime\Core\Public\Containers/IndirectArray.h:218]
FSkeletalMeshRenderData::Serialize(FArchive&, USkinnedAsset*)+0x18 [Engine\Source/Runtime\Core\Public\Serialization/Archive.h:1980]
USkeletalMesh::Serialize(FArchive&)+0x43c [Engine\Source/.\Runtime/Engine/Private/SkeletalMesh.cpp:1872]
StaticDuplicateObjectEx(FObjectDuplicationParameters&)+0x960 [Engine\Source/.\Runtime/CoreUObject/Private/UObject/UObjectGlobals.cpp:0]
StaticDuplicateObject(UObject const*, UObject*, FName, EObjectFlags, UClass*, EDuplicateMode::Type, EInternalObjectFlags)+0xdd [Engine\Source/Runtime\Core\Public\Containers/Set.h:335]
DuplicateObject_Internal(UClass*, UObject const*, UObject*, FName)+0x48 [Engine\Source/.\Runtime/CoreUObject/Private/UObject/UObjectGlobals.cpp:0]

This is on Unreal 5.4 but I suspect the root issue may still exists in UE 5.7 although I couldn’t test it as calling DuplicateObjecton a skeletal mesh in that version of the engine systematically crashes on a Nanite resource duplication. Is there any additional change we could make to the engine or the duplication code to prevent this crash from happening ?