Nonstring indices of a keyed table are converted to strings when sent through a remote

When sending a table as a remote’s parameter, if any of it’s indices are userdata or another table, then those indicies will be a string when received on the client.

For example,
A table shown below is sent to the client.

{
    [game.Workspace.Baseplate] = 1, 
    [TweenInfo] = "what", 
    [{1}] = 36,
    [function() end] = "yes",
    ["constant"] = true
}

The client receives the following table instead:

 {
    ["<Instance> (Baseplate)"] = 1, 
    ["<Table> (table: 0x189dd80d06144b32)"] = "what", 
    ["<Table> (table: 0x1ac5eba3cf65d672)"] = 36,
    ["<Function> (function: 0xcd38e1c7fda40e42)"] = "yes",
    ["constant"] = true
}

As you can see, the nonstring indicies are converted into strings, never converted back to the actual data type that was given.
This does not happen in tables that have strictly numerical indicies.

Steps to reproduce:

  • Open up a new game in studio and publish it.
  • Create a Script in ServerScriptService, LocalScript in StarterPlayerScripts, and a RemoteEvent in ReplicatedStorage
  • Send the table shown above to the client through that RemoteEvent
  • When received on the client, iterate through the table printing the indicies and their data types

Or you can just use the file below:
repro.rbxl (18.5 KB)

This bug happens in studio and in games, I remember not too long ago we were able to send non-string indicies through a remote and it would be received in the proper format. I never saw an announcement about this changing so I’m pretty sure this is a bug that needs to addressed as such a sudden unannounced change could cause a lot of problems with existing games.

This is not a bug, but a limitation. Functions can never be sent and, according to Roblox (at least a couple years ago) never will be able to be sent.
The rule of thumb is that you can transfer the same things you can save in DataStores.
Numbers, booleans, strings. Am I forgetting anything?

1 Like

It’s not a mixed table, all indecies are set as keys and none are numbers.

And if this is a limitation as @JarodOfOrbiter claims , it is not documented here in “Parameter Limitations” so it is either a bug or they made a huge hiccup when failing to document this.
https://developer.roblox.com/en-us/articles/Remote-Functions-and-Events

This even happens with a table that has a single key and value.

{[game.Workspace.Baseplate] = 1}

will be received as

{["<Instance> (Baseplate)"] = 1}

This is not a mixed table in the slightest, but we are still receiving the wrong information.

1 Like

I was just about to edit my reply, you are correct and I don’t know what I was thinking. Still true of functions though.

You’re right, my terminology is wrong. I understand your problem better now.

I don’t recall that being the case. Internally maps and dictionaries are serialized with string keys. I guess maybe now it does typeof(v) + tostring(v) for non-string keys.

2 Likes

I’m pretty sure you used to be able to send at least tables and userdata as indicies and get them back how you sent them as roblox would convert automatically, but this is no longer the case. This behavior is not documented as a limitation of remote events which leads me to believe that this is unindented, but I could be wrong and in that case all they need to do is update their documentation.

I have been dissecting the Roblox network protocol since 2017, and at no point has there been a way for a table to be serialized with table/userdata keys and sent over the network. Only two types exist; (a dictionary with string keys) and an array type (with integer keys). Tables and most Roblox userdata can be passed as the contained values, but never as table keys. That is, and has been, a hardcoded limitation of the engine.

It is true that the documentation is a bit unclear about this. DevHub does warn you about mixed tables, though: https://developer.roblox.com/en-us/articles/Remote-Functions-and-Events

2 Likes

Thank you for the reply, I still believe this should be documented as this is not a mixed table and the data is lost through the transfer with no explanation given. I will make a documentation request soon and link it here once made, lack of documentation leads me to believe that this is a bug so we’ll see what happens.

I can verify that this is not a bug. Roblox replication only supports string->Variant maps and arrays without gaps.

2 Likes

Couldn’t it be considered a bug that the call goes through, rather than throwing a descriptive error?

5 Likes

Maybe initially back when it was introduced. Now I doubt it would be feasible for us to change that behavior without breaking too many scripts.

1 Like

Maybe rather than an error that could break existing code it should at least throw a warning as this data is suddenly lost with no explanation. Either that, or add it to the documentation about remote parameter limitations.

No there’s not, it clearly says that the data can be passed, but in this case the data is lost and there isn’t documentation for that.

2 Likes

Bumping this because I just found out that I can’t send a table over the network like
[workspace.Baseplate] = true

anymore without the key getting converted into a string. Yet the devhub still says otherwise

2 Likes