Many of us have encountered the error Cannot convert mixed or non-array tables: keys must be strings
. Perhaps not recently, though. Why is that?
It seems that the methods that used to throw these errors have begun to put up with them. You can put together a very simple unit test and see that if you try to save a mixed table to a DataStore or pass it from server to client (or vice-versa), no error will be thrown, but the table will have dropped all its string-keyed values and anything past the first missing integer index. And without any warning, I might add.
That is, only if the table contains a value at index 1.
If, for example, we take the following table and pass it from server to client (as a return from a RemoteFunction invocation), something very bizarre happens:
local perpetrator = {[2] = true}
This little guy will wreak havoc in your codebase. Let’s check out what happens.
- The client prints the error
Cannot convert mixed or non-array tables: keys must be strings
(which, we can all agree, is an incredibly unspecific and unhelpful error message) and references the line where RemoteFunction:InvokeServer was called. - The server prints… nothing. It acts as though no issue occurred on its end, which can lead its developer to think the error was only in client code.
-
Every subsequent call to InvokeServer on this RemoteFunction REGARDLESS OF WHICH CLIENT calls it returns the same
Cannot convert mixed or non-array tables: keys must be strings
error. Yes, it breaks that RemoteFunction for all players. Again, it does this without printing a single message in Server log.
To be specific, here are the only steps needed to reproduce:
- Call RemoteFunction:InvokeServer from a client
- The server’s OnServerInvoke returns the above mentioned table
Here is a minimal repro file (17.6 KB) containing some helpful comments. It includes a button that you can press to initiate the errors so that you can test it from two clients – one presses the button and the other doesn’t, but they both suffer the consequences.
Resolutions:
- The RemoteFunction should continue to operate as expected for all clients despite encountering the error
- All mixed tables should throw an error, or none of them should.
- The server log should display an error, and (bonus) an even more specific message about what was wrong with the table (i.e. it has string keys and a numerical key, or it has all numerical keys but one is missing, perhaps the depth in the table that this problem was encountered, the position in the tuple being returned [when multiple values are being returned by the function], etc).
OR
Stop using JSON (I assume that’s the reason for the limitations) to transfer/store tables and use something that supports native Lua tables. I realize that serializing Lua tables is not a complex issue, but the more complex issue here is modifying existing code and migrating existing DataStores. Even that doesn’t seem that complex to me, but maybe I’m missing something.