"Keys Must Be Strings"


This error would be much more helpful if it told me:

  1. The DataStore I am trying to save to that failed
  2. What the line of code was
  3. What the value and type of the key I tried to save was
  4. What the value associated with that key I tried to save was

Alternative feature request: “Fix” the JSON parser in the HttpService to accepts maps (ex: {[1] = true, [3] = true,[7] = false}) and mixed values (ex: {1,2,This=true}).

Both of those aren’t in valid JSON format though.

1 Like



I’m changing the message to:

Cannot convert tables with non-string keys: keys must be strings

but I was wondering if you all could help me come up with a error message that is more clear.

Edit: Updated error message proposed, old idea was: Cannot convert mixed tables: all keys must be strings or all keys must be integers

1 Like

I don’t think that error is right, you can’t have arbitrary numerical indices either. In any table or sub-table that you save to datastores you can only have all string indices, or consecutive numerical indices from 1 to any integer n. (Because it has to be converted to JSON)

I either suggest changing this error message so that it’s something like “Tables can only have either string indices, or subsequent numerical indices starting at 1”, or you should change the JSON parser so that it can handle all sorts of table indices. (See the other thread Shedletsky points to for some discussion and a possible solution for that) I assume the second one may not be an option right now so go for the more descriptive error instead.

Yeah, you’re right. I just updated the message as you said that, but it’s not exactly clear. Perhaps

Cannot convert non-array tables with non-string keys: keys must be strings

How about

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

Maybe the word “mixed” here should be something else (can’t really think of the proper term), but I think an error like that would cover it quite well.

1 Like

You’re right! The problem isn’t with the JSON parser, but with the Lua table parser on the C-Side, which is using a specific data-class that can only accept strings as a key.

Modifying the JSON parser to not use this class is perhaps an option.

Yep! Going with that option!

In response to this:

I suspect this error is that your code is in pcall, and you aren’t catching errors from it.

With this error, the error occurs for more than just datastores. I’m going to look into providing more information.

This is very possible. To be honest, I forget, this thread is from 2 weeks ago.

I wonder if the information exists in the Lua VM at the time of the crash to give a reasonable error message regardless?

On the client side, maybe catching the exception and rethrowing it might provide more information. There is enough information, this code will reproduce the error with a line count:

local Function = Instance.new("BindableFunction")
		OwnedProductsSet = { [3453255] = true }

Alternative feature request: Maybe stop using JSON? I don’t see a reason to use JSON if you never see it or need to edit it, especially when it’s not even compatible with Lua tables in the wild.

Store it in some nice, small, binary format that can store any kind of table, and allows for recursion (if you solve recursion, is solves every other problem)

1 Like

You are going to have to talk slower, lol.

I don’t even understand how that is valid Lua syntax. :huh:

How can you Invoke something that is not a function. Invoking a declaration makes no sense at all to me.

Yeah. JSON is a bad choice for the reasons I outlined here - http://devforum.roblox.com/t/datastore-keys-must-be-strings/24837

Most of these are better: http://lua-users.org/wiki/TableSerialization

1 Like

Try my format!! :slight_smile:

local t={}


111 00000  10000 1 000 10000 1 000 10000 1

Somehow you managed to make Lua code look like assembly.

It is at the same time both wondrous and abominable :happy3:

Instance.new returns an object, in this case being a BindableFunction object, which has an Invoke method, just like Instance.new(“Part”) has a Destroy method, so

local Part = Instance.new("Part")

is just as valid as Quenty’s code.

Did I win?

Do you use this on Roblox? What do you do to get around strings becoming null-terminated when passed to the Roblox API?