From 4.19 to 4.21 - incompatible_unique_net_id

After switching from 4.19 to 4.21 clients could not connect to dedicated server anymore.
I build UE4 from the source, rebuild dedicated server from the source, Package project with UE 4.21 Source Build but clients could not connect anymore.

Tried more than once, but no effect. When client try to connect server shows :
Prelogin failure: incompatible_unique_net_id

Any suggestions?

Yes i am after a fix for this as well i just switched today and am having the same issue

Iā€™ve been having this same issue, but only with Android connecting to a dedicated server. Windows can still connect.

It seems to be caused by attempting to use OnlineSubsystemUNSET. But Iā€™ve selected to use OnlineSubsystemOculus, and Iā€™m in the process of figuring out why it appears to be UNSET instead.

Here are some of my logs around this:
UE4 : [2018.12.07-22.53.35:481][522]LogGameMode: Display: Match State Changed from InProgress to LeavingMap
UE4 : [2018.12.07-22.53.35:481][522]LogGameState: Match State Changed from InProgress to LeavingMap
UE4 : [2018.12.07-22.53.35:481][522]LogNet: Browse: 35.197.7.152//Game/SculptureMode
UE4 : [2018.12.07-22.53.35:482][522]LogInit: BSD_Android: Socket queue 65536 / 65536
UE4 : [2018.12.07-22.53.35:483][522]LogInit: BSD_Android: I am localhost (127.0.0.1:0)
UE4 : [2018.12.07-22.53.35:483][522]LogSockets: (BSD_Android) Wifi Adapter IP 127.0.0.1
UE4 : [2018.12.07-22.53.35:484][522]PacketHandlerLog: Loaded PacketHandler component: Engine.EngineHandlerComponentFactory (StatelessConnectHandlerComponent)
UE4 : [2018.12.07-22.53.35:484][522]LogNet: Game client on port 7777, rate 500000000
UE4 : [2018.12.07-22.53.35:676][536]LogNetVersion: SculptrVR 1.0.0.0, NetCL: 0, EngineNetVer: 5, GameNetVer: 0 (Checksum: 1388534187)
UE4 : [2018.12.07-22.53.35:677][536]LogNet: UPendingNetGame::SendInitialJoin: Sending hello. [UNetConnection] RemoteAddr: 35.197.7.152:7777, Name: IpConnection_0, Driver: PendingNetDriver IpNetDriver_0, IsServer: NO, PC: NULL, Owner: NULL, UniqueId: INVALID
UE4 : [2018.12.07-22.53.35:718][539]LogModuleManager: Warning: ModuleManager: Module ā€˜OnlineSubsystemUNSETā€™ not found - its StaticallyLinkedModuleInitializers function is null.
UE4 : [2018.12.07-22.53.35:788][544]LogNet: NetConnection::Close() [PendingNetDriver] [NoPC] [No Owner] from NMT_Failure incompatible_unique_net_id

Ok I found the culprit.

Either in 4.20 or 4.21 Epic changed the PreLogin function in GameModeBase.cpp.

Now it verifies that both the server and the client are using the same OnlineSubsystem type.

I have tried overriding that function in my GameMode to allow any connection. It connects to the server successfully! But now it crashes :stuck_out_tongue: Iā€™ll have to report back later if I can get it to work.

Btw, the super suspicious line is:
UE4 : [2018.12.07-22.53.35:718][539]LogModuleManager: Warning: ModuleManager: Module ā€˜OnlineSubsystemUNSETā€™ not found - its StaticallyLinkedModuleInitializers function is null.

I donā€™t know why it would ever try to load OnlineSubsystemUNSET instead of OnlineSubsystemNULLā€¦

Iā€™m experiencing the same issues and havenā€™t found a work around yet.

Did you figure out a way?

There are details and the solution here: https://answers.unrealengine.com/questions/815780/typehash-invalid-with-a-custom-online-subsystem.html

This is my isolated reply/solution from that post:


Found the fix for the hash issue. Instead of adding a hash, given the "fix" implemented by Epic in 4.20.3, we now need to override the following function in FUniqueNetIdUWorks, inherited from FUniqueNetId:

virtual FName GetType() const override
{
    return TEXT("UWorks");
}

Sorry for the troubles everyone, I wrote that to avoid our QA causing late night, last minute fires when we are trying to ship games. As you probably know, any commandline addition of the form
-no<ossname> will disable an online subsystem. We use at least 7 at any given time, so its possible for mistakes to be made.

Many use this for different reasons, but what happened all to often (and on a Friday night no less) would be the server would be fine but some client would have one of these set. Our servers would assert that the FUniqueNetId wasnā€™t serializing the right type to play our game. QA would freak out and bug it but it was always user error.

I added this explicit check because I figured externally most teams expect compatible unique ids. As it would seem it has been discovered, you are free to remove the check in AGameMode::Prelogin().

That being said, Iā€™m curious, how do you get around the automatic calls to RegisterPlayer that would probably complain. Do you overload these functions? Do you not use the session interface to manage multiplayer sessions? Just want to understand the paths you are treading.

Most client/server relationships should be talking compatible OnlineSubsystems. For example, it makes little sense for a Steam client to join a non Steam server and not authenticate. A lot of that pipeline was written in the base engine implementation. APlayerState has one FUniqueNetId, which should be the one defined by DefaultPlatformSubsystem in your DefaultEngine.ini file.

Thanks for chiming in @Crzyhomer !

My solution was to remove the check in PreLogin and then yeah it created problems converting between FUniqueNetId types. So I Made a routine that could convert everything into a NULL online subsystem unique ID (which is basically just a string) and the server just keeps those around.

Thanks for the reply. In my case, Iā€™m using Steam for clients and player hosted listen servers but then using official dedicated servers without steamā€™s online subsystem for simplicities sake. I made a simple server browsing system for those dedicated servers. The complexity for most people to host a dedicated server increases quite a lot when you add SteamCMD into the mix. Itā€™s going to be a free community ā€œblueprintsā€ project, so Iā€™d like to avoid modifying the engine. And because itā€™s free, the project doesnā€™t require any of the auth checks and such. Staying with a blueprint only multiplayer project has proven to be quite the challenge.

Iā€™ve seen a few people having problems with UE20+ using Android clients mixing with null subsystems as well, if I remember right. Iā€™m guessing they might be running into a similar problem.

Iā€™m spanning quite a lot of different skill sets here and maybe I just donā€™t fully understand what the best route should be. I understand we should probably just be querying the steam SDK with OnlineSubsystemNull instead of using OnlineSubsystemSteam, but we are just trying to keep everything simple.

I realize Epicā€™s cross platform online service was announced recently. My tentative plan was to wait until that matures. (Unless it will be a long time.) Maybe I should just scrap that idea and use Steam for dedicated servers.

That sounds like a good solution. Maybe Epic can implement a method like that in the future releases? Were you only experiencing crashes with the conversion between FUniqueNetId types?

Thanks, Iā€™m strongly considering using UWorks in the future. Youā€™ve done some fine work there.

Hi,

Thank you for giving us more information on why exactly these changes were made. What Iā€™m trying to figure out is how we are expected to implement ā€œcross-platformā€ client/server. You mention that you would expect if you are using a steam client, to also be using a steam server online subsystem. The type check changes make sense if that is the assumption, but if you want to use a steam client with your own online subsystem how exactly are we suppose to approach this?

From my understanding, you expect the developer to create their own online subsystem (letā€™s call it TestOnlineSubSystem) and create their own UniqueID (FUniqueNetIdTest, which derives from unique net id etc). When the user boots up the game on steam / xbox / ps4 / epic launcher letā€™s say, they will be using that specific subsystem (xbox, ps4 etc). Where are we suppose to handle the conversion from FUniqueNetIdSteam (this is replicated from client to server by the means of FUniqueNetIdRepl) to FUniqueNetIdTest (on the server) in order to be used for TestOnlineSubSystem so that the type checking will pass?

Currently in order to get around this, I implemented my own uniqueID and inside the PreLogin / InitNewPlayer functions I will create my own subsystems type and pass that through and it will work, but I dont really understand what official approach to your new implementation should be. It appears that many developers are having the same problems / questions regarding this.

@Crzyhomer

I used to be able to use the command ā€œopen ExampleMap?listenā€ on PC
and then connect using ā€œopen [PCā€™s IP Address]ā€ on my iOS/Android device to quickly test out multiplayer, but now this crashes the game.
If you can, please fix this and let us know, thanks!

The check in Prelogin was meant to keep compatible ā€œDefaultā€ OnlineSubsystems together and alert if they are incompatible for reasons alluded to here, including registration and just basic FUniqueNetId incompatibility. The engine tries to do various things for you AGameSession::RegisterPlayer for example and things will just break if you pass incompatible FUniqueNetIds around.

That being said PC obviously doesnā€™t have any console interface because there is simply no API from them to do so. Some people have been using the OnlineSubsystemNULL as the default subsystem for both clients/servers but it wasnā€™t really meant to be a production system as it doesnā€™t support many features you need.

Depending on what you are doing, you could try to start with this (DefaultPlatformService=NULL) so both servers/clients have a common OSS. Depending on the feature set you may need to extend NULL. We pass the PlatformUniqueNetId to the AGameMode::Login call by extending ULocalPlayer::GetGameLoginOptions (?PlatformId=someConsoleId/etc) and then the dedicated server holds on to that via CreateForeignUniqueNetId so it can be replicated/compared/etc even though it canā€™t be directly useful off the native platform. Replicating to other players is super important for parties and other reasons.

Beacons donā€™t care about most of this, other than say passing around an FUniqueNetId as part of the handshaking. Console session management has to occur on the clients since a Linux/PC server doesnā€™t understand console APIs.

You can access any OnlineSubsystems directly from the code via IOnlineSubsystem::Get(World, NAMEOFSUBSYSTEM). For Fortnite we wrap this call into GetPlatformOnlineSubsystem() which returns Xbox/PS4/Switch/etc based on compiled platform. The common interface makes it so it doesnā€™t really matter what platform we are talking to for registration/voice/cloud save/etc.

The overall point isnā€™t about converting from UniqueId to another, but maintaining parallel OnlineSubsystems to get the data between clients through agnostic replication on the server. There is no universal OnlineSubsystem yet that can talk across platforms. The one we have in Fortnite is what weā€™re trying to expose via the Epic Online Services SDK which is underway right now.

You can see its beginnings at dev.epicgames.com or the various blogs that talk about our services roadmap. To be clear this SDK does not require our store, but our current implementations arenā€™t ready for public consumption yet.

Can mention where it is crashing? Server in PreLogin or elsewhere? Have you set your default OSS to NULL or disabled all subsystems?

Thanks for the update! This is what I suspected would come as a part of the epic online subsystem which will eventually be released.

Iā€™m on 4.22 an i have an issue with players on steam connection to a non steam dedicated server.
I figured out that subsystems now need to be the same and removed that check like described here.

I now have a problem that the server crashes as a player joins. Itā€™s probably about the problems converting between FUniqueNetId types, but Iā€™m not sure.

Can anyone help me with that?

I attached the end of my Server log file with the crash.

Thanks in advance.

Note, I am not using steam on my dedicated server, connecting via raw IP, and so client side I removed all steam net definitions in the DefaultEngine.ini

[OnlineSubsystemSteam]
bUseSteamNetworking=false
ā€¦ other stuff

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
NetDriverDefinitions=(DefName=ā€œGameNetDriverā€,DriverClassName="/Script/OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
+NetDriverDefinitions=(DefName=ā€œDemoNetDriverā€,DriverClassName="/Script/Engine.DemoNetDriver",DriverClassNameFallback="/Script/Engine.DemoNetDriver")

[OnlineSubsystem]
DefaultPlatformService=Steam
ā€¦ other stuff

DO NOT HAVE
[PacketHandlerComponents]
/Script/OnlineSubsystemSteam.SteamNetDriver

I then had to hack the engine in PendingNetGame.cpp by commenting out the following line
//Connection->PlayerId = LocalPlayer->GetPreferredUniqueNetId();

WARNING: I have zero clue what other ramifications there are having a default PlayerId, but I know thatā€™s whats happening if you run the game via editor or run the game without the steam client running.

1 Like

Thanks man! It saved at least a day for me :slight_smile: I mean the last line.
I had the same issue with Oculus Online Subsystem, because its UniqueNetID format is not compatible with NULL OSS, and if I removed the format check in GameModeBase::PreLogin() it crashed my Linux server, but if no ID is sent, it works fine with Gamelift :slight_smile: btw ID is passed as UNKNOWN similarly when testing from Editor. And Gamelift uses its own PlayerSessionID, so apparently no more problems so farā€¦

1 Like

//Connection->PlayerId = LocalPlayer->GetPreferredUniqueNetId();
This change no longer works in UE 4.27
Has anyone been able to solve the problem in the latest available Unreal Engine 4 version (4.27)?

it does work in 4.27, we have a released game :slight_smile: