Bindable Function - Cannot convert mixed or non-array tables: keys must be strings

Hello! I have come across an issue that has never happened to me before the new lua vm, maybe it was just my uses for it but this worked before so :P
I have a table that records player movement for each part in their character that runs a few times per second, when i need this data, i use a bindable function to get the table
the table is structured as follows

{
    0 = { -- UserId
        1 = { -- the iteration in this part, this needs to be a number so that i can do table.insert(table,1,data), so that the newest one is always 1.
            "Part" = part.CFrame, -- This however, needs to be a key, so that i can easily get the part i'm looking for's cframe
            "timestamp" = tick()
        }
    }
}
-- New data is added to this every 10th of a second then data older than 5 seconds is cleared

I currently have no way to convert this to an all key or all number table, and this wasn’t an issue before. I currently cannot progress until i have a fix for this, any help on this would be greatly appreciated.

1 Like

You basically need to convert the CFrame to a string that you can later reverse engineer back into the CFrame, something like so will do,

{
    0 = {
        1 = {
            "Part" = tostring(part.CFrame),  -- Saves the CFrame in a string form
            "timestamp" = tick()
        }
    }
}

and to reverse engineer that, you can just use matrices like so,

local function ReverseStringToCFrame(x)
	local a = {}
	for m in x:gmatch'[^,]+' do
		a[#a+1] = tonumber(m)
	end
	return CFrame.new(unpack(a))
end

Okay so first, that’s not the problem, the problem isn’t the data, it’s the keys
I can’t send this table over a bindable function/event for instance:

local t = {"owo", owo = "owo"}

because one would be t[1] == “owo” and the other is t[“owo”] == “owo”, the problem is that
roblox doesn’t like me sending a table that’s mixed between integers and keys (strings).
edit: nvm sorry i swear i tested that, i will try your solution again
edit 2: Yeah, it still didn’t work, oof

1 Like

My bad my bad, I thought what you meant was that you couldn’t pass CFrame through since it wasn’t a string, I don’t really use bindables much but having seen that error, I figured it works somewhat similar to how datastores are, because datastores too, don’t take mixed tables, and CFrame etc needs to be converted into a string first.

I do wonder if that remains the case with bindables though, having to convert CFrame to string, keep me updated though if it does solve your issue, cause if it does then it’s true I guess that it works just how datastores do :+1:

This is not a new problem, see:

The problem your having stems from the fact that you have number indices and string indices. You know what your data should look like and be able to use a number of different table formats.

For example, using only number indices/arrays: {“Part”, part.CFrame}
Or using tostring and tonumber to convert your number indices to strings while sending it through and back on the other side.

Try converting the UserId to a string. I know that to work you should have to convert the iteration to a string too, but it worked for me when I just converted the UserId.

If that doesn’t work, you could convert the iteration too and write a custom table.insert to work with string indexes. Here’s an example of how it might look, but I’m sure there’s a better way to do this.

local yourTable = {
	["0"] = {
		["1"] = {
			["Part"] = CFrame.new(), -- etc, just an example of what the indexes look like
		}
	}
}

-- string version of table.insert
local function tableInsert(list, pos, value)	
	if list[tostring(pos)] then
		tableInsert(list, pos + 1, list[tostring(pos)])
	end
	
	list[tostring(pos)] = value
end

@A1_exe The reason that it’s not so simple to convert is because he needs to be able to get the part’s CFrame easily and also needs to use table.insert. His post said this, so I’m not sure why you acted like he didn’t know that.

1 Like

thank you, i wouldn’t have thought to convert the table during the invoke, here’s what I did!

local function convertTable(t)
	local returnedTable = {}
	for i,v in pairs(t) do
		if typeof(i) == "number" then
			i = tostring(i)
		end
		if typeof(v) == "table" then
			returnedTable[i] = convertTable(v)
		else
			returnedTable[i] = v
		end
	end
	return returnedTable
end

Since the data doesn’t need to be edited after the invoke this solution is perfect, again thank you!