Table stored in DataStore2 not updating

I am storing a table of items the player owns in DataStore2 and when they open a case I want to update but the value is not saving to DataStore2.
When I leave the game and rejoin the data is suddenly gone and when I open another case the data is gone and replaced with the item from the latest case.

local data = ToolsDataStore:Get()
print(data) -- returns {} because data does not save from previous sessions
table.insert(data, Item)
print(data) -- returns {[1] = "Whatever the item name is"}
ToolsDataStore:Set(data)
	
print(ToolsDataStore:Get()) -- returns {[1] = "Whatever the item name is"}

How can I fix this? Thanks

Why are you using GetTable and not Get again? It should return the correct value if you use Get

I used Get() in my code, I don’t know why it says GetTable() in the post. The code still doesn’t work.

1.Do you have any other values left after you exit that are not related to the table? Maybe you just didn’t create the bool value named “SaveInStudio” in ServerStorage and didn’t set it to true ?
image
image

  1. Is this the structure of your main script responsible for datastore2?
DataStore2.Combine("DATA", "tablef")

Players.PlayerAdded:Connect(function(player)
	local tableStore = DataStore2("tablef", player)
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local tablef = tableStore:Get({})
	tableStore:OnUpdate(function(newValue)
		tablef = newValue
	end)
end)

Perhaps you forgot to combine the resulting table?

DataStore2.Combine("DATA", "tablef")

SaveInStudio is in ServerStorage and is set to true.
My script looks like the one shown.
I did combine the DataStore.

I’m not sure what the problem could be because every other DataStore is working fine.

I still think it’s about the structure of your script responsible for datastore2, since you can still use Get() and Set() functions in other scripts.

Could you send source code for me?

This is the entire script that handles datastores.

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")

local IncrementEvent = ReplicatedStorage.Increment

local DataStore2 = require(ServerScriptService.DataStore2)
DataStore2.ClearCache()

DataStore2.Combine("DATA", "Bucks")
DataStore2.Combine("DATA", "XP")
DataStore2.Combine("DATA", "Rebirths")
DataStore2.Combine("DATA", "Tools")
DataStore2.Combine("DATA", "Equipped Tools")

Players.PlayerAdded:Connect(function(player)
	
	local BucksDataStore = DataStore2("Bucks", player)
	local XPDataStore = DataStore2("XP", player)
	local RebirthsDataStore = DataStore2("Rebirths", player)
	local ToolsDataStore = DataStore2("Tools", player)
	--local EquippedToolsDataStore = DataStore2("Equipped Tools", player)
	
	-- Functions to interpet data
	
	-- Functions to update leaderstats

	local function SetBucksLeaderstat()
		player.leaderstats.Bucks.Value = BucksDataStore:Get()
	end

	local function SetLevelLeaderstat()

		local XP = XPDataStore:Get()
		local Level = 1
		local RequiredXP = 100

		-- Iterate until we find the correct level
		while task.wait() do
			if XP >= RequiredXP then
				Level = Level + 1 -- Move to the next level
				XP = XP - RequiredXP -- Subtract XP used to level up from XP
				RequiredXP = RequiredXP + 100 -- Increase the XP required for the next level
			else
				player.leaderstats.Level.Value = Level
				break
			end
		end
	end
	
	-- Functions to update inventory
	
	local function UpdateInventory(Value)
		
		-- Add item to inventory
		
		if Value then
			
			local Item = Value

			local data = ToolsDataStore:Get()
			print(data)
			table.insert(data, Item)
			print(data)
			ToolsDataStore:Set(data)
			
			print(ToolsDataStore:Get())
			
		end
		
		-- Update Inventory
		
		--[[for i,v in ToolsDataStore:Get() do
			print(v)
			for i,w in ipairs(require(game.ReplicatedStorage.ToolsModule)) do
				if v == w.Name then
					require(game.ReplicatedStorage.ToolsModule).AddToolToInventory(player.UserId, w.Name, w.Description, w.Rarity, w.ImageId)
				end
			end
		end]]
		
	end
	
	-- Updates data when remote event called

	IncrementEvent.Event:Connect(function(UserId, DataStore, Value)

		if UserId == player.UserId then		
			if DataStore == "XPDataStore" then
				XPDataStore:Increment(Value)				
				SetLevelLeaderstat()
			end
			if DataStore == "BucksDataStore" then
				BucksDataStore:Increment(Value)
				SetBucksLeaderstat()				
			end
			if DataStore == "ToolsDataStore" then
				UpdateInventory(Value)
			end
		end
	end)
	
	-- Load players data when they join
	
	player:WaitForChild("leaderstats")
	player.leaderstats:WaitForChild("Bucks")
	player.leaderstats:WaitForChild("Level")
	
	if BucksDataStore:Get() == nil then
		BucksDataStore:Set(0)
	else
		SetBucksLeaderstat()
	end

	if XPDataStore:Get() == nil then
		XPDataStore:Set(0)
	else
		SetLevelLeaderstat()
	end
	
	if ToolsDataStore:Get() ~= nil then
		UpdateInventory()
	end
	
	-- Equip players previously equipped tools when they join
	
	--if EquippedToolsDataStore:Get() ~= nil then
		--[[print(EquippedToolsDataStore:Get())
		for i,v in EquippedToolsDataStore:Get() do
			for i,w in ipairs(require(game.ReplicatedStorage.ToolsModule)) do
				if v == w.Name then
					require(game.ReplicatedStorage.ToolsModule).EquipTool(player.UserId, w.Name, w.Description, w.Rarity, w.ImageId)
				end
			end
		end]]
	--end
	
end)

First of all, I have never seen such an unorganized space in my life

Second, this script work for me:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")

local IncrementEvent = ReplicatedStorage.Increment

local DataStore2 = require(ServerScriptService.DataStore2)
DataStore2.ClearCache()

DataStore2.Combine("DATA", "Bucks")
DataStore2.Combine("DATA", "XP")
DataStore2.Combine("DATA", "Rebirths")
DataStore2.Combine("DATA", "Tools")
DataStore2.Combine("DATA", "Equipped Tools")

Players.PlayerAdded:Connect(function(player)

	local BucksDataStore = DataStore2("Bucks", player)
	local XPDataStore = DataStore2("XP", player)
	local RebirthsDataStore = DataStore2("Rebirths", player)
	local ToolsDataStore = DataStore2("Tools", player)
	--local EquippedToolsDataStore = DataStore2("Equipped Tools", player)
	
	local toolsData = ToolsDataStore:Get({})

	-- Functions to interpet data

	-- Functions to update leaderstats

	local function SetBucksLeaderstat()
		player.leaderstats.Bucks.Value = BucksDataStore:Get()
	end

	local function SetLevelLeaderstat()

		local XP = XPDataStore:Get()
		local Level = 1
		local RequiredXP = 100

		-- Iterate until we find the correct level
		while task.wait() do
			if XP >= RequiredXP then
				Level = Level + 1 -- Move to the next level
				XP = XP - RequiredXP -- Subtract XP used to level up from XP
				RequiredXP = RequiredXP + 100 -- Increase the XP required for the next level
			else
				player.leaderstats.Level.Value = Level
				break
			end
		end
	end

	-- Functions to update inventory

	local function UpdateInventory(Value)

		-- Add item to inventory


		local Item = Value

		local data = ToolsDataStore:Get()
		print(data)
		table.insert(data, Item)
		print(data)
		ToolsDataStore:Set(data)

		print(ToolsDataStore:Get())


		-- Update Inventory

		--[[for i,v in ToolsDataStore:Get() do
			print(v)
			for i,w in ipairs(require(game.ReplicatedStorage.ToolsModule)) do
				if v == w.Name then
					require(game.ReplicatedStorage.ToolsModule).AddToolToInventory(player.UserId, w.Name, w.Description, w.Rarity, w.ImageId)
				end
			end
		end]]

	end

	-- Updates data when remote event called

	IncrementEvent.Event:Connect(function(UserId, DataStore, Value)

		if UserId == player.UserId then		
			if DataStore == "XPDataStore" then
				XPDataStore:Increment(Value)				
				SetLevelLeaderstat()
			end
			if DataStore == "BucksDataStore" then
				BucksDataStore:Increment(Value)
				SetBucksLeaderstat()				
			end
			if DataStore == "ToolsDataStore" then
				UpdateInventory(Value)
			end
		end
	end)

	-- Load players data when they join

	player:WaitForChild("leaderstats")
	player.leaderstats:WaitForChild("Bucks")
	player.leaderstats:WaitForChild("Level")

	if BucksDataStore:Get() == nil then
		BucksDataStore:Set(0)
	else
		SetBucksLeaderstat()
	end

	if XPDataStore:Get() == nil then
		XPDataStore:Set(0)
	else
		SetLevelLeaderstat()
	end

	if ToolsDataStore:Get() ~= nil then
		UpdateInventory("idk")
	end

	-- Equip players previously equipped tools when they join

	--if EquippedToolsDataStore:Get() ~= nil then
		--[[print(EquippedToolsDataStore:Get())
		for i,v in EquippedToolsDataStore:Get() do
			for i,w in ipairs(require(game.ReplicatedStorage.ToolsModule)) do
				if v == w.Name then
					require(game.ReplicatedStorage.ToolsModule).EquipTool(player.UserId, w.Name, w.Description, w.Rarity, w.ImageId)
				end
			end
		end]]
	--end

end)

And I also don’t see the point in using ClearCashe. Previously, it was used to clear the entire date in the datastore, but now, apparently, this function is deprecated

I also see a lot of unnecessary code in your script, I advise you to thoroughly study the api of datastore2: How to use DataStore2 - Data Store caching and data loss prevention - Resources / Community Tutorials - Developer Forum | Roblox

And there simple example of datastore2 main code:

local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local Workspace = game:GetService("Workspace")

local DataStore2 = require(ServerScriptService.DataStore2)

-- Combine every key you use. This will eventually be the default, but for now read the "Gotchas" section to understand why we need this.
DataStore2.Combine("DATA", "points")

Players.PlayerAdded:Connect(function(player)
    local pointsStore = DataStore2("points", player)

    local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"

    local points = Instance.new("NumberValue")
    points.Name = "Points"
    points.Value = pointsStore:Get(0) -- The "0" means that by default, they'll have 0 points
    points.Parent = leaderstats

    pointsStore:OnUpdate(function(newPoints)
        -- This function runs every time the value inside the data store changes.
        points.Value = newPoints
    end)

    leaderstats.Parent = player
end)

--The player will now have leaderstats

--Now, we have to let the player actually get points. Write the following code after the connection:


Workspace.PointsPart.ClickDetector.MouseClick:Connect(function(player)
    local pointsStore = DataStore2("points", player)
    pointsStore:Increment(1) -- Give them 1 point
end)
1 Like

Thanks a lot for the help. I added task.wait(5) as the first line in the UpdateInventory() function and it fixed everything. I removed DataStore2.ClearCache() from my code and changed the functions that would set leaderstats when you first join the game to longer check if the user has data and use DataStore:Get(default value) instead. Could you elaborate more on how my code is unorganized? To me everything is compartmentalized and easy to understand, but that’s probably just because I wrote it.

First, you don’t need to split the combination of one container into different lines.

I prefer this option more:
DataStore2.Combine("DATA", "Bucks", "XP", "Rebirths", "Tools", "Equipped Tools")

Secondly, since I have not seen your new script, I will say in advance that for int, float, etc. values, it is best to create new values yourself, as presented in this code:

local leaderstats = Instance.new("Folder")
    leaderstats.Name = "leaderstats"

local points = Instance.new("NumberValue")
    points.Name = "Points"
    points.Value = pointsStore:Get(0) -- The "0" means that by default, they'll have 0 points
    points.Parent = leaderstats

Third, do not forget that ABSOLUTELY all values need to be constantly updated:

pointsStore:OnUpdate(function(newPoints)
        -- This function runs every time the value inside the data store changes.
        points.Value = newPoints
    end)

And last but not least, this is my personal taste - do not write various functions and events in the code block itself, where you create and update your values, because this is, in fact, the center of your entire economy.

The leaderstats are created in another script, but I will move them to this one. I stopped using the :OnUpdate() function because I couldn’t get it to recognize when a value was changed outside of the script the :OnUpdate() function was in. As for creating functions inside of this script, is there a way to make it so if one function errors the rest of the script doesn’t stop with it and keeps functioning? Could I acheive that with spawn(function()?

The fact is that the :onUpdate function is always launched when you use the :Set() function and it changes the value not for the server, but for local scripts (this is a kind of thin thread between the server and the client), this in turn is necessary for various actions (for example, without the onUpdate function, your gui stats (if any) simply will not be to be updated:

LocalScript:

game.Players.LocalPlayer.Leaderstats.Points.Value.Changed:ConnectFunction()
       TextLabel.Text = game.Players.LocalPlayer.Leaderstats.Points.Value
end)

If you want the function not to stop your script in case of an error, then you need to use pcall:

Players.PlayerAdded:Connect(function(player)	
	pcall(function()
		local f = player.Value -- error
	end)
	print("heheee")
end)

Thanks. For updating values I call a BindableEvent and the script included above then updates the values. If the values need to be sent to the client, I’ll send them to client then through a remote.

Well, yes, it already depends on the person how he will manage his economy.

I was glad to help you. The main thing is, next time, do not forget to study the module you are using better. :wink:

I will. I’m still unsure what was wrong though because task.wait(5) doesn’t seem like something that would fix data not saving lol. I had to do this when saving the Bucks and XP values in the round system because otherwise the value I saved second would not save.

Bucks:Increment(1)
task.wait() -- removing this causes XP to not save
XP:Increment(1)

When I tested your script, I was able to get a data even without task.wait, you just have to set up default value of table in your main script:

By the way, I just noticed that you used a remote event to change the values in the datastore. And I really hope that you don’t start this remote event from the client, because the fact is that hackers can at any time not only start the remote function themselves, but also change the values that come to the server.

That is, they can simply run a remote event where the value is 10000000000

It’s a BindableEvent because I couldn’t get DataStore:OnUpdate() to recognize when I use DataStore:Increment(number) in another script. If I could get that to work then I would just trigger the functions from DataStore:OnUpdate() and instead of calling a BindableEvent when I want to update something I would just do DataStore:Increment(number).