Sorry for delay!
ServerSettingsData is a TArray<uint8> that is serialized data from a AServerSettings actor, which is a child of AInfo. This is replicated early via a UGameInstance::HandleGameNetControlMessage override. Calls to get server settings on client then does the conversion from the bytes to a AServerSettings actor, that is then cached on the game instance as a UPROPERTY pointer.
This also occurs on Development builds. I suspect this happens in shipping builds too, but shipping doesn’t care about -1 indexing into GUObjectArray - it just ignores if index is invalid.
Here is the callstack. UGenericGameLibrary::GetServerSettings is where Convert is called.
ARecastNavMesh::PostLoad() RecastNavMesh.cpp:622
UObject::ConditionalPostLoad() Obj.cpp:1356
[Inlined] UE::Trace::FChannel::operator|(const UE::Trace::FChannel &) Channel.inl:30
FAsyncPackage2::Event_DeferredPostLoadExportBundle(FAsyncLoadingThreadState2 &, FAsyncPackage2 *, int) AsyncLoading2.cpp:9015
FEventLoadNode2::Execute(FAsyncLoadingThreadState2 &) AsyncLoading2.cpp:5713
FAsyncLoadEventQueue2::ExecuteSyncLoadEvents(FAsyncLoadingThreadState2 &) AsyncLoading2.cpp:5919
FAsyncLoadingThread2::ProcessLoadedPackagesFromGameThread(FAsyncLoadingThreadState2 &, bool &, TArrayView<…>) AsyncLoading2.cpp:9292
FAsyncLoadingThread2::TickAsyncLoadingFromGameThread(FAsyncLoadingThreadState2 &, bool, bool, double, TArrayView<…>, bool &) AsyncLoading2.cpp:9556
FAsyncLoadingThread2::FlushLoading(TArrayView<…>) AsyncLoading2.cpp:11241
FlushAsyncLoading(TArrayView<…>) AsyncPackageLoader.cpp:362
FlushAsyncLoading(int) AsyncPackageLoader.cpp:331
LoadPackageInternal(UPackage *, const FPackagePath &, unsigned int, FLinkerLoad *, FArchive *, const FLinkerInstancingContext *, const FPackagePath *) UObjectGlobals.cpp:1781
LoadPackage(UPackage *, const FPackagePath &, unsigned int, FArchive *, const FLinkerInstancingContext *, const FPackagePath *) UObjectGlobals.cpp:2145
LoadPackage(UPackage *, const wchar_t *, unsigned int, FArchive *, const FLinkerInstancingContext *) UObjectGlobals.cpp:2121
StaticLoadObjectInternal(UClass *, UObject *, const wchar_t *, const wchar_t *, unsigned int, UPackageMap *, bool, const FLinkerInstancingContext *) UObjectGlobals.cpp:1430
StaticLoadObject(UClass *, UObject *, const wchar_t *, const wchar_t *, unsigned int, UPackageMap *, bool, const FLinkerInstancingContext *) UObjectGlobals.cpp:1476
[Inlined] LoadObject(UObject *, const wchar_t *, const wchar_t *, unsigned int, UPackageMap *, const FLinkerInstancingContext *) UObjectGlobals.h:2084
FObjectAndNameAsStringProxyArchive::operator<<(UObject *&) ArchiveUObject.cpp:194
[Inlined] FBinaryArchiveFormatter::Serialize(UObject *&) BinaryArchiveFormatter.h:282
[Inlined] FStructuredArchiveSlot::operator<<(UObject *&) StructuredArchiveSlots.h:364
FObjectProperty::SerializeItem(FStructuredArchiveSlot, void *, const void *) PropertyObject.cpp:237
FPropertyTag::SerializeTaggedProperty(FStructuredArchiveSlot, FProperty *, unsigned char *, const unsigned char *) PropertyTag.cpp:582
UStruct::SerializeVersionedTaggedProperties(FStructuredArchiveSlot, unsigned char *, UStruct *, unsigned char *, const UObject *) Class.cpp:1853
UStruct::SerializeTaggedProperties(FStructuredArchiveSlot, unsigned char *, UStruct *, unsigned char *, const UObject *) Class.cpp:1503
UObject::SerializeScriptProperties(FStructuredArchiveSlot) Obj.cpp:1977
UObject::Serialize(FStructuredArchiveRecord) Obj.cpp:1741
UObject::Serialize(FArchive &) Obj.cpp:1601
AActor::Serialize(FArchive &) Actor.cpp:992
[Inlined] FObjectSerializer::Convert(FMemoryReader &, UObject *, AServerSettings *&) ObjectSerializer.h:64
[Inlined] FObjectSerializer::Convert(FMemoryReader &, UObject *) ObjectSerializer.h:97
UGenericGameLibrary::GetServerSettings(UObject *) GenericGameLibrary.cpp:1889
AGamePlayerController::ClientEnableFeature_Implementation(bool) GamePlayerController.cpp:10841
UFunction::Invoke(UObject *, FFrame &, void *const) Class.cpp:7460
UObject::ProcessEvent(UFunction *, void *) ScriptCore.cpp:2209
AActor::ProcessEvent(UFunction *, void *) Actor.cpp:1465
FObjectReplicator::ReceivedRPC(FNetBitReader &, const FReplicationFlags &, const FFieldNetCache *, const bool, bool &, TSet<…> &) DataReplication.cpp:1402
FObjectReplicator::ReceivedBunch(FNetBitReader &, const FReplicationFlags &, const bool, bool &) DataReplication.cpp:1178
UActorChannel::ProcessBunchInternal(FInBunch &) DataChannel.cpp:3751
[Inlined] UActorChannel::ProcessBunch(FInBunch &) DataChannel.cpp:3843
UActorChannel::ReceivedBunch(FInBunch &) DataChannel.cpp:3558
[Inlined] UChannel::ReceivedSequencedBunch(FInBunch &) DataChannel.cpp:594
UChannel::ReceivedNextBunch(FInBunch &, bool &) DataChannel.cpp:1160
UChannel::ReceivedRawBunch(FInBunch &, bool &) DataChannel.cpp:730
UNetConnection::DispatchPacket(FBitReader &, int, bool &, bool &) NetConnection.cpp:3940
UNetConnection::ReceivedPacket(FBitReader &, bool, bool) NetConnection.cpp:3308
UNetConnection::ReceivedRawPacket(void *, int) NetConnection.cpp:2147
UIpNetDriver::TickDispatch(float) IpNetDriver.cpp:1293
UNetDriver::InternalTickDispatch(float) NetDriver.cpp:2202
[Inlined] Invoke(void (UNetDriver::*)(float), UNetDriver *&, float &&) Invoke.h:66
[Inlined] UE::Core::Private::Tuple::TTupleBase::ApplyAfter(void (UNetDriver::*&)(float), UNetDriver *&, float &&) Tuple.h:320
TBaseUObjectMethodDelegateInstance::ExecuteIfSafe(float) DelegateInstancesImpl.h:689
[Inlined] TMulticastDelegateBase::Broadcast(float) MulticastDelegateBase.h:258
TMulticastDelegate::Broadcast(float) DelegateSignatureImpl.inl:1080
UWorld::Tick(ELevelTick, float) LevelTick.cpp:1341
UGameEngine::Tick(float, bool) GameEngine.cpp:1898
FEngineLoop::Tick() LaunchEngineLoop.cpp:5621
[Inlined] EngineTick() Launch.cpp:60
GuardedMain(const wchar_t *) Launch.cpp:189
LaunchWindowsStartup(HINSTANCE__ *, HINSTANCE__ *, char *, int, const wchar_t *) LaunchWindows.cpp:271
WinMain(HINSTANCE__ *, HINSTANCE__ *, char *, int) LaunchWindows.cpp:339
That was the failure case, which only happens outside of the first connection. This is creating a second RecastNavMesh on client after it has already been destroyed because bNetLoadOnClient==false. The package being requested is the persistent level, which I believe is AServerSettings’ outer since one isn’t set.
I’m not sure why the package load request from the Convert call doesn’t happen on first connection.