DataStore2 "table expected, got string" error

I’ve got a working DataStore2 script, and it saves everything as it should except for the player’s inventory. Everything else is a stringvalue, but I need the inventory to be a table of tool names.

This is all my values defined:

 	local dataArmor = DataStore2("Armor",plr)
	local dataStyle = DataStore2("Style",plr)
	local dataTaunt = DataStore2("Taunt",plr)
	local dataWeapon = DataStore2("Weapon",plr)
	local dataTools = DataStore2("ToolDS",plr)

And this is the script segment that tries to load it:

if (dataTools:Get()==nil) then return end
	for _,v in pairs(dataTools:Get()) do
		print(v)
		if require(config).ToolStorage:FindFirstChild(v) then
			table.insert(ActualTools, v)
		end
	end

This returns the “Table expected, got string” error. Because it’s a string, of course.
dataTools is what I want to be a table, but when I try to say:

local dataTools = {
		"Kingdom Key",
		"Potion",
	}

And set it up as a table, it returns an error at this line

	if (dataTools:Get()==nil) then return end

Saying “attempt to call a nil value.”

I’m very confused on saving dictionaries to DataStore2, and I’ve looked at all the other posts I can find but none of them seem to work. Any help is appreciated.

you don’t really need to add :Get() since its a table

Thanks, that actually seems to have fixed it! But now another problem arises, when trying to save using the following code:

	local ActualTools = {}
	game.Players.PlayerRemoving:Connect(function()
		print("Saving tools")
	local SG = plr:WaitForChild("StarterGear")
	for _,v in pairs(SG:GetChildren()) do
		table.insert(ActualTools, v.Name)
	end
	if ActualTools[1] then
				dataTools:Set(ActualTools[1])
				print(ActualTools[1])
			else
		end
	end)

It returns the same error with dataTools:Set() saying “attempt to call a nil value.”
So now that I have the initial tools, how do I add additional ones to the table?

Could I table.insert the ActualTools into dataTools then :Save() dataTools?

dataTools:SetAsync(ActualTools[1])

It still returns nil, even when using :SetAsync But I can’t tell which value it is that is nil, the ActualTools or the dataTools, because they both should be non-nil given that the script loads in dataTools and inserts it properly.

Are you trying to save 1 item in the ActualTools? If not.

local dataTools = game:GetService("DataStoreService"):GetDataStore("DataTools")
local ActualTools = {}

game.Players.PlayerRemoving:Connect(function()
	print("Saving tools")
	local SG = plr:WaitForChild("StarterGear")
	for _,v in pairs(SG:GetChildren()) do
		table.insert(ActualTools, v.Name)
	end
	
	local success, errorMessage = pcall(function()
		dataTools:Set(ActualTools)
	end)
	
	if errorMessage then
		warn(errorMessage)
	end
end)

Still returns nil, just yellow instead of red.

I inserted print(ActualTools) and print(dataTools) after the

table.insert(actualTools, v.Name)

And they both returned the expected list of items. So both tables are confirmed non-nil by the time I’m trying to :Set() the actual tools as the data ones. I really don’t know what value it’s referring to as nil.

Wait I don’t get it what is your dataTools a table?

Yeah, when printed it returns something like this

[1] "Potion"
[2] "Bond of Flame"
[3] "Kingdom Key"

Bruh! if you want to save a data the do local dataTools = game:GetService("DataStoreService"):GetDataStore("DataTools")

I know how to work it with the normal Roblox DataStore, but my players were experiencing a lot of data lossage with the Roblox version, so I’m trying to convert it to DataStore2.

Why not just put all of this into one table and save it. and get the table using the DataStore2() since you saved it in here.

Here is an example of my datastore 2 script I have made into a module. Maybe you could learn from this.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local HttpService = game:GetService("HttpService")
local AntiDataLossModule = require(script.Parent.AntiDataLossSystem)
local TextCompress = require(script.Parent.Parent.Misc.TextCompression)
local LevelFunctions = require(script.Parent.Parent.Misc.NumberAlgorithms.LevelFunctions)
local CommaSuffixer = require(script.Parent.Parent.Misc.NumberAlgorithms.CommaSuffixer)
local DefaultData = require(script.DefaultData)

local LeaderstatsToCreate = {{"Level", "IntValue"}, {"Coins", "StringValue"}, {"Gems", "StringValue"}, {"Eggs Hatched", "StringValue"}}

local RegularData = {}

function UpdateStats(plr, StatData) -- Sets all the leaderstats values when the Data is edited.
	ReplicatedStorage.RemoteEventsAndFunctions.Ui.UpdateUiStats:FireClient(plr, StatData)
	for item, leaderstat in pairs(StatData) do
		if plr.leaderstats:FindFirstChild(item).Value ~= leaderstat then
			plr.leaderstats:FindFirstChild(item).Value = leaderstat
		end
	end
end

function RegularData:SetUpData() -- Sets up the players data and combines the dictionary key to the reset key.
	AntiDataLossModule.Combine(ReplicatedStorage.DataResetKey.Value, "Dictionary")
end

function RegularData:SaveAllPlayerData() -- Loops through the players and saves there data.
	for number, plr in ipairs(game.Players:GetPlayers()) do
		if plr then
			AntiDataLossModule("Dictionary", plr):Save()
		end
	end
end

function RegularData:GrabData(plr) -- Grabs data for the player.
	local Data = AntiDataLossModule("Dictionary", plr)
	Data:SetBackup(5)
	local GrabData = Data:GetTable(DefaultData)
	if Data:IsBackup() then
		plr:Kick("Sorry, but your data did not load correctly. Try rejoining to fix this problem...")
	end
	return GrabData
end

function RegularData:EditData(plr, ChangedData) -- Changes the players data to the changed data table.
	local Data = AntiDataLossModule("Dictionary", plr)
	if not Data:IsBackup() then
		Data:Set(ChangedData)
		local StatData = self:FindStatsDataToUpdate(ChangedData)
		UpdateStats(plr, StatData)
	end
end

function RegularData:FindStatsDataToUpdate(data) -- Returns all the stats that need updated on the leaderstats in a table format.
	local ReturnedStatTable = {}
	for number, stat in ipairs(LeaderstatsToCreate) do
		if number == 1 then
			ReturnedStatTable[stat[1]] = LevelFunctions:GetLevelFromExp(data["Experience"]["Value"])
		else
			ReturnedStatTable[stat[1]] = CommaSuffixer:Suffixate(data[stat[1]]["Value"])
		end
	end
	return ReturnedStatTable
end

return RegularData

But that’s not the issue, the other stats already save. The issue is that ToolDS is not saving.

This seems to have different syntax than what I’m using, also it looks like your stats are already saved as strings and you just update those. I can do that.

What I’m trying to do is create a table, called ToolDS, and be able to add StringValues to the table that are the names of weapons which the player owns.
I can already get a list of the items a player has, I just can’t save that list to the DataStore2 as ToolDS.