CharacterMovementComponent NetGUID missing on server after seamless travel

We’re on 4.4. We have an issue where clients are getting kicked from a game after a servertravel. So player A hosts a listen server. Player B connects to that server. Player A triggers a servertravel. Player B gets kicked from the server after spawning into the new map with the following error on the server.

[2014.09.18-20.42.27:361][ 2]LogNetPackageMap:Warning: InternalLoadObject: Unable to resolve object (not in cache). NetGUID: 141
[2014.09.18-20.42.27:361][ 2]LogNetTraffic:Error: UActorChannel::ReadContentBlockHeader: Unable to read sub-object class. Actor: PlayerClass_C_3
[2014.09.18-20.42.27:361][ 2]LogNet:Error: UActorChannel::ReceivedBunch: ReadContentBlockHeader FAILED. Bunch.IsError() == TRUE. Closing connection.

After dumping the NetGUIDs I see that 141 is referring to Engine.CharacterMovementComponent. So the kick happens when the server tries to serialize the class object for the client Character movement component. Engine.CharacterMovementComponent is missing from the server’s NetGUIDLookup but the client has it correctly. The GuidSequence for both client and server are the same.

So I’m trying to figure out why CharacterMovementComponent is missing from the server’s NetGUIDLookup. As far as I can tell it should be there or it should be added when the server receives a bunch for the Character. CleanReferences seems to get called correctly for both but CharacterMovementComponent never gets added to the new NetGUIDLookup on the server.

Any ideas about where the problem might be or something I can looked out for?

I looked into CleanReferences and that seems like it is working properly. On the server CharacterMovementComponent is removed from ObjectLookup and then NetGUIDLookup because it is static. Although I’m not 100% sure what constituents a static/dynamic guid. On the client the reference is kept in both maps. The problem seems to be that the server doesn’t readd this reference as is implied by the comment “(server will assign a new guid to static references after a seamless travel)”.

Can anyone provide or point to a explanation of how the NetGUID creation/destruction with seamless travel pipeline should flow?

Some more information. I noticed that CharacterMovementComponent was the only object on the client that was being assigned a default FNetworkGUID inside of GetOrAssignNetGuid()s if !IsNetGUIDAuthority() block. It looks like this is due to ServerMove being called, which triggers this if it does not already have a NetGUID assigned, before the ‘normal’ way.

With that in mind I moved ServerMove to ACharacter and CharacterMovementComponent’s function was renamed to ServerMove_Internal. So just piping the RPC through the actor instead of directly to the component. The result was that the client did not get kicked when travelling with the server and everything worked as expected.

So it seems like this situation only occurs when an actor has a component with a server RPC that is calling that RPC before it’s been assigned a NetGUID by the server.

Any updates on this issue? Another solution I’ve found is keeping CleanReferences from doing anything by simply returning early so clients down clean their net cache. It seems to be an issue with static members. I’m not sure what the consequences of returning early in CleanReferences could be.