Search Unity

Understanding NetworkReader:ReadByte out of range errors

Discussion in 'Multiplayer' started by any_user, Oct 14, 2015.

  1. any_user

    any_user

    Joined:
    Oct 19, 2008
    Posts:
    374
    I regularly have errors like this:

    Code (CSharp):
    1. IndexOutOfRangeException: NetworkReader:ReadByte out of range:NetBuf sz:8 pos:8
    It happens when changing any line of code in a script, even though it's not changing anything about the networking functionality. Creating a new build normally solves the problem.

    For example I added some debug logging to debug my client interpolation, but adding a simple print() command already breaks compatibility with the build, where the server is running. Is there a way to work around this or do I really have to create a new server build every time I change something on the client?

    Also I don't completely understand what this message exactly means, except that there's some problem with reading the network data. Why can't it read the data when nothing about the network changed? Is there a way to find the object that's causing it?

    Right now it basically this means every time we do a tiny fix for any platform we have to rebuild all builds for all platforms. In our case we have a crossplatform networked game where players play together on PC, Mac, Linux, iOS, Android, PS4 and PSVita, so it would be impossible to make even a tiny platform-specific update without going through several reviews by Sony, Apple, etc.?
     
    Last edited: Oct 14, 2015
  2. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
  3. any_user

    any_user

    Joined:
    Oct 19, 2008
    Posts:
    374
    One example: I just was working on a project, created a build, then started a server. Then I connected to it with the editor, everything worked. Then I added a print(somevalue) line somewhere in a script. I started the game in the editor again, connected to the server, and got the error.

    I had this several times, but I can't really reproduce it. Once I created an android build right after creating a server build, which showed this error. I double-checked if it both were the most recent builds, and they were both made from the same project. But the server worked with all other builds (standalone, ios) except the android one. I rebuilt the android build, but it didn't help.

    Then I rebuilt all of them without changing anything, and it worked again. First I thought I used the wrong builds, but after several times having the same issue I'm starting to think that something doesn't work like it should.. or maybe I just don't completely understand what UNET is doing behind the scenes. Is there anything happening in the background which I might not be aware of?

    Next time I'll try debugging with the tools you mentioned, maybe it helps, thanks!
     
  4. chrismarch

    chrismarch

    Joined:
    Jul 24, 2013
    Posts:
    472
    That sounds like a bug to me. I am not sure how it could occur, unless you save your script changes before making sure the editor is not playing, or unless you are running into exceptions after your change.
     
  5. Roiw

    Roiw

    Joined:
    Jan 15, 2013
    Posts:
    23
    You are absolutely right, I just had the same problem and did a rebuild. Wonder what that is..
     
  6. Roiw

    Roiw

    Joined:
    Jan 15, 2013
    Posts:
    23
    Has anyone ever figured this out? I still have those errors from time to time.. its very annoying.
     
  7. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    I've never run across this, but it does sound like a bug to me. If you look at the debug statement at the very end.

    sz:8 pos:8 -

    It's just a guess, but bytes array containers are usually 0 based indexes, so if it's a size of 8 you can't read position 8, you can only read up to position 7.
     
  8. Roiw

    Roiw

    Joined:
    Jan 15, 2013
    Posts:
    23

    It changes from time to time for instance I just got the error again today and now it says:


    Screen Shot 2016-03-14 at 2.36.34 PM.png
     
  9. Freakyuno

    Freakyuno

    Joined:
    Jul 22, 2013
    Posts:
    138
    Yea, that still makes sense. In a size 5 array, you can only index up to position integer 4, because you start at 0
     
  10. atgczcl

    atgczcl

    Joined:
    Aug 6, 2013
    Posts:
    2
    try use like this(my error is gone!)
    string message = msg.ReadMessage<StringMessage>().value;

    and this (error is on, throw errors !):
    netMsg.reader.ReadString()
     
  11. HanSun

    HanSun

    Joined:
    Aug 18, 2016
    Posts:
    2
    Just call NetworkMessage.NetworkReader.SeekZero() to reset pointer before reading from the NetworkMessage.
     
    ovrdb likes this.
  12. HanSun

    HanSun

    Joined:
    Aug 18, 2016
    Posts:
    2
    public void OnSetGroupState(NetworkMessage netMsg)
    {
    netMsg.reader.SeekZero();
    PulseMessages.SetGroupStateMsg msg = netMsg.ReadMessage<PulseMessages.SetGroupStateMsg> ();
     
    ovrdb likes this.
  13. Clawf

    Clawf

    Joined:
    Jul 29, 2014
    Posts:
    2
    I have the same bug, 1 year after you. It is exactly as you described it.
     
  14. suxinren

    suxinren

    Joined:
    Jan 13, 2017
    Posts:
    14
    Thank you Han Sun.Your answer perfectly solves my problem.
     
  15. martaaay

    martaaay

    Joined:
    Apr 13, 2009
    Posts:
    136
    HanSun or suxinrenzs, can you explain a little more about this code?
     
    jethrogillgren likes this.
  16. MostHated

    MostHated

    Joined:
    Nov 29, 2015
    Posts:
    1,235
    That is strange, I am still getting an error using the code @HanSun posted, but also another one from the actual code he posted.

    Code (CSharp):
    1. [Exception] NullReferenceException: Object reference not set to an instance of an object
    2. WorldEngine.IncomingOperationHandler()    Assets/_Components/_Server/_Server/WorldEngine.cs:107
    3. 105:   {
    4. 106:       //var msg1 = msg.reader.ReadBytesAndSize();
    5. -->107:       msg.reader.SeekZero();
    6. 108:       var deserial = NOC.Deserialize(msg.reader.ReadBytesAndSize());
    7. 109:       Debug.Log(deserial);
    8.  
    I am also getting :
    Code (CSharp):
    1. [Exception] [NetBuffer] [] [21.140] (15) IndexOutOfRangeException: NetworkReader:ReadByte out of range:NetBuf sz:0 pos:0
     
  17. Macklin

    Macklin

    Joined:
    Jun 13, 2015
    Posts:
    11
    Bit of a necropost, but I found that when re-using NetworkMessages (e.g. to manually send them to multiple handlers), the start position of the reader would be wherever the last handler left it, resulting in this error message and garbled or failed deserialization. Figured SeekZero would help, but it seemed to result in a different garbled message. That is until I found out that the reader in some, but not all of my messages started at position 4 instead of 0. I assume this is for some other data contained within the NetworkMessage.

    In this case, when I used ReadMessage, it would only property deserialize if the reader position was at 4 beforehand. If I called ReadMessage twice in a row, the second resulting object would be garbled, as the reader position would have shifted the length of the bytes read.

    So basically in order to read data from an already-read NetworkMessage, you need to skip the first 4 bytes by reading any 4-byte type (int32, float...) or with ReadBytes(4). However, I think most of the Read methods will read from 0 if the reader position is the length of the last thing that was read - not entirely sure.

    Code (CSharp):
    1. msg.reader.SeekZero();
    2. msg.reader.ReadBytes(4);
    3. var myMsg = msg.ReadMessage<MyMessage>();
    And yes, the documentation says nothing about this. Perhaps ReadMessage should be changed to reset the reader position after deserializing?
     
    dolphincup likes this.