Remote event weird behavior when passing through hashed table

So recently, I was scripting a basic boss system for my game when I came across a neat little error. The error itself said Invalid table key type used , now I, of course, took the time to search the dev forums to see if anyone else had encountered this. I came across two accounts in which this error was resolved by different individuals. Now as you all may know, when firing remote events Roblox will error if there is a mixed table being passed through (tables with keys that have both hash and numerical keys). So I decided to see if this was the problem with the table I was passing through but unfortunately, it wasn’t that easy to fix this error. I managed to print what the keys were for this table and concluded that the table I was passing through was indeed not a mixed table. So I’m wondering, is there a reason why this error occurred, if anyone out there has encountered it and has a solution I’m in need of help at the moment.

function Module.FireRemoteEvent(RemoteName, IsAll, ...)
	local RemoteData = Module.GetRemoteEvent(RemoteName)
	if not RemoteData then return warn("Could Not Find RemoteData") end

	local RemoteInstance = RemoteData[1]
	if RemoteInstance then
		if RunService:IsServer() then
			if IsAll then
				return RemoteInstance
				return RemoteInstance
		if RunService:IsClient() then
			return RemoteInstance

^ wrapper function for network communication (ignore this as it is not why the error is occurring).

NetworkUtility.FireRemoteEvent("UpdateUserstats", true, "UpdateBosses", BossInformation["Zone"], ActiveBossesData)

^ what was being passed through, I’ve made some modifications since then but try to ignore the messiness of it all. I’m simply prototyping atm.

Alright, I can’t wait to read some of your solutions! Thank you for reading :smile:

It is exactly what it says it is.
Remote functions and events can only send 2 types of tables:

  1. Arrays
  2. Dictionarys with string keys only

One of the values you are passing in is a dictionary whose keys are not strings or numbers
Which one of them it is, I do not know. Either BossInformation[“Zone”] (aka BossInformation.Zone) or ActiveBossesData.

I’ve tooken the time to print the values being passed in that table and all the keys are all strings. Does it matter if there is a nested array within the table being passed through?

For example:

local myTable = {
  ["KeyOne"] = {["SubKey"] = {Array}, -- or
  ["KeyTwo"] = {Array},

Does this also apply?

Are you sure you checked their types too? Some of the values can be tostring()'d like parts. And have you checked all of them? You could be doing something like bosses[bossObject] = lookupData

Try using this function before sending that remote event over:

local func = type --or use typeof
local function typeDump(t, l, checked)
    l = (l and l .. "\t") or ""
    checked = checked or {t}
    for k, v in next, t do
        if type(v) == "table" and not checked[v] then
            checked[v] = true;
            typeDump(v, l, checked)

Yes, I have checked the initial keys of the table being passed through. However, if you mean whether or not every table is a key or value then I cannot tell since I haven’t ran a deep check function like you’ve mentioned. Here is the output when I look through the keys before sending: image

EDIT: I did type(i) that is why it’s printing “string”

Also, after trying what I suggested, see if it still errors when not sending that table over if all the data seems accurate in the output.

It’s not about whether the key is numerical or not, it’s about whether or not it goes into the array or dictionary part of the table.

Still seems to error. But if interested, here is the output. image

Nothing seems to be out of place, and the keys seem to be there as anticipated. I can’t understand why it’s erroring though.

perhaps it is this?

I am not sure if it accepts numerical keys that are out of array range.

I don’t quite get what you mean, mind elaborating?

Try sending it after deleting AttackingPlayers or clearing it.

I use the player’s userId to hold track of players currently attacking the boss in the system. I can change it into a string via tostring function if that’ll change anything.

It should fix the issue if it is a string.

Like I mentioned before. Also I accidentally typed numerical, it only accepts string key dictionaries.

One reason, just taking a guess, that this could be erroring is if there is an array that doesn’t start with the index of 1 it will throw the Invalid table key type used error. For example this array would error:

local Table  = {

{[2] = 2, [3]= 4}


Numeric keys do not go into the array portion of the table just because they are numbers. Generally, ignoring holes, if your table doesn’t have values at keys from 1 to the maximum number, the higher values will go into the dictionary part. and not the array. Hole behavior is more complicated.

It doesn’t have to start at an index of 1 actually because it will replace those fields with null afaik. It has to be either classified as an array or a string key dictionary, and based on the array size and the space between indices, it chooses which part a numerical index would land in (array or dictionary part).

Yes, I was a bit confused when you said

because I was really sure that wasn’t the case but I trust your judgment, I’ve turned it to a string and the error seems to be gone. However, can you elaborate on what took place here? I was under the impression that it was only the tables passed through directly that were affected by the Roblox checks (first generation tables is what I mean). This is a nested table within the passed in the table which had a numerical index. I’m still a bit confused.

I will leave this thread here. This thread is a good example of how bad Roblox’s design decision was. Lua programmers should mostly not need to know the difference between array and hashtable portions of tables.

Roblox has to serialize all the information it uses to communicate to the server and to the client, it does not just magically send objects and text over. It might be using JSON or some other type of storage format to do so but their serializer / type cannot handle those occasions.