4.24 to 4.25 upgrade issue with GC reference token stream assert

Hi,

I am having an issue with upgrading our project from 4.24 to 4.25Plus (as we aim to consoles rather than pc). The engine seems to have a problem with our UCLASS marked class inheriting from UObject - let’s call it ADeleteMeMngr. Upon startup, the engine halts on every UObject variable that is marked UPROPERTY within mentioned ADeleteMeMngr.

It is important to say, the class is pretty big, containing UFUNCTIONS, regular functions, UPROPERTIES, regular variables, and a lot of TArray variables.

The execution stops on those UObject inherited properties not having correct offset (offset of the first var is 766416, so starts with 00010 in bit value, which it shouldn’t according to the assert). Seems the offset should not be this high.

From the call stack, it seems the problem is happening when creating Reference Token Stream for that class for GC. And from the code docs, it seems that offsets are given to each property in Link().

If I let the engine continue through asserts, the editor starts up and the functionality I tested within the editor seems fine (except for creating a build, as it seems to get stuck on the very same assert).
This issue is specific to that class and no other. I have checked other classes with the same UCLASS parameters, and similar variables, but none have the same issue.

Just removing UPROPERTY mark on UObject variables makes VS not stop execution of engine, but is not a solution we want to go with as we need the functionality UPROPERTY provides (including replication).

I tried duplicating the class (renamed and detached from other code) and the issue appeared also on duplicated class. I kept reducing it and eventually, the assert stopped happening on the duplicated class.

Particularly I removed functions without UFUNCTION mark and then I started to remove TArray variables. It seemed that the issue was not tied to any particular TArray variable. Just having fewer TArray variables seemed to have caused Unreal to give to the UObject properties normal offsets which passed through assert.

So currently my suspicion is that the class got too big and for whatever reason it caused UPROPERTIES to receive too high offsets.

This was not an issue on 4.24. Since 4.25 brought optimization to UPROPERTIES making them FField rather than UObject, I suspect this is correlated as in 4.24 that same assert is limited to

 check( (InOffset & ~0xFFFFF) == 0 );

Is there a limitation from 4.25 as to how big a UClass using UPROPERTIES should be?

**Or for that matter is using a lot of TArrays, which apparently move offset of UObject properties now a bad design? **

With your change in offset assertion, why not place in assertion which checks the size of the class if it is now limited?

Or am I wrong and the problem is related to something else?

The class looks something like this

#pragma once

#include "Containers/Array.h"
...several libraries specific to project
#include "Math/Vector.h"

#include "DeleteMeMngr.generated.h"

struct FConfiguration;
struct FParams;
class USomething;


UCLASS(Blueprintable, BlueprintType)
class ADeleteMeMngr : public AInfo
{
	GENERATED_BODY()
private:
	static const int MaxVar = 4000;
	static const int MaxVar2 = 1000;

public:
	ADeleteMeMngr();

private:
//This property is not problematic (and so are other non UObject inheriting vars)
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = deletemanager, meta = (DisplayName = "Platform Max Num"))
	TMap<EPlatform, uint8> PlatformMaxNum;
	
//Problematic property
	UPROPERTY()
	TMap<TSubclassOf<AThing>, FTypeConfiguration> TypeMap;

//Problematic property
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
	TSubclassOf<AThing> Class;
...
Contains a lot of UPROPERTIES which are not inheriting from UObject, UFUNCTIONS, a lot of TAarray variables
...

protected:
//Problematic property
	UPROPERTY(BlueprintReadWrite, Category = deletemanager, meta = (AllowPrivateAccess = true))
	ASomeManager* SomeManager;
};