Datastore not working / not existing?

I’ve created this datatstore that saves data stored in the player but it never says it has successfully saved and it also never loads the data even though it says its successfully loaded? I’m guessing the data does not exist?

--[Varibles]--
local datastoreService = game:GetService("DataStoreService")
local playerData = datastoreService:GetDataStore("playerData")
local inventory = datastoreService:GetDataStore("playerData")


--[Datastore & Leaderstats]--
game.Players.PlayerAdded:Connect(function(player)
	local dataFolder = Instance.new("Folder", player)
	dataFolder.Name = "Data"
	local mainFolder = Instance.new("Folder", dataFolder)
	mainFolder.Name = "Main"
	local rankVarible = Instance.new("StringValue", mainFolder)
	rankVarible.Name = "Rank"
	local equiptWeaponVarible = Instance.new("StringValue", mainFolder)
	equiptWeaponVarible.Name = "EquiptWeapon"
	local equiptAccessoryVarible1 = Instance.new("StringValue", mainFolder)
	equiptAccessoryVarible1.Name = "EquiptAccessory1"
	local equiptAccessoryVarible2 = Instance.new("StringValue",  mainFolder)
	equiptAccessoryVarible2.Name = "EquiptAccessory2"
	local equiptArmorVarible1 = Instance.new("StringValue",  mainFolder)
	equiptArmorVarible1.Name = "EquiptArmor1"
	local equiptArmorVarible2 = Instance.new("StringValue", mainFolder)
	equiptArmorVarible2.Name = "EquiptArmor2"
	local equiptAbilityVarible1 = Instance.new("StringValue", mainFolder)
	equiptAbilityVarible1.Name = "EquiptAbility1"
	local equiptAbilityVarible2 = Instance.new("StringValue", mainFolder)
	equiptAbilityVarible2.Name = "EquiptAbility2"
	local equiptAbilityVarible3 = Instance.new("StringValue", mainFolder)
	equiptAbilityVarible3.Name = "EquiptAbility3"
	local equiptAbilityVarible4 = Instance.new("StringValue", mainFolder)
	equiptAbilityVarible4.Name = "EquiptAbility4"
	local equiptAbilityVarible5 = Instance.new("StringValue", mainFolder)
	equiptAbilityVarible5.Name = "EquiptAbility5"
	local equiptAbilityVarible6 = Instance.new("StringValue", mainFolder)
	equiptAbilityVarible6.Name = "EquiptAbility6"
	
	local data = playerData:GetAsync(player.UserId)
	if data then
		rankVarible.Value = data.rankVarible
		equiptWeaponVarible.Value = data.equiptWeaponVarible
		equiptAccessoryVarible1.Value = data.equiptAccessoryVarible1
		equiptAccessoryVarible2.Value = data.equiptAccessoryVarible2
		equiptArmorVarible1.Value = data.equiptArmorVarible1
		equiptArmorVarible2.Value = data.equiptArmorVarible2
		equiptAbilityVarible1.Value = data.equiptAbilityVarible1
		equiptAbilityVarible2.Value = data.equiptAbilityVarible2
		equiptAbilityVarible3.Value = data.equiptAbilityVarible3
		equiptAbilityVarible4.Value = data.equiptAbilityVarible4
		equiptAbilityVarible5.Value = data.equiptAbilityVarible5
		equiptAbilityVarible6.Value = data.equiptAbilityVarible6
	else
		rankVarible.Value = "F-"
	end
	print("Sucessfully loaded:".. " ".. player.Name.. "s".. " Data.")
end)

game.Players.PlayerRemoving:Connect(function(player)
	local data = {
		rankVarible = player.Data.Main.Rank.Value,
		equiptWeaponVarible = player.Data.Main.EquiptWeapon.Value,
		equiptAccessoryVarible1 = player.Data.Main.EquiptAccessory1.Value,
		equiptAccessoryVarible2 = player.Data.Main.EquiptAccessory2.Value,
		equiptArmorVarible1 = player.Data.Main.EquiptArmor1.Value,
		equiptArmorVarible2 = player.Data.Main.EquiptArmor2.Value,
		equiptAbilityVarible1 = player.Data.Main.EquiptAbility1.Value,
		equiptAbilityVarible2 = player.Data.Main.EquiptAbility2.Value,
		equiptAbilityVarible3 = player.Data.Main.EquiptAbility3.Value,
		equiptAbilityVarible4 = player.Data.Main.EquiptAbility4.Value,
		equiptAbilityVarible5 = player.Data.Main.EquiptAbility5.Value,
		equiptAbilityVarible6 = player.Data.Main.EquiptAbility6.Value,
	}
	playerData:SetAsync(player.UserId, data)
	print("Sucessfully saved:".. " ".. player.Name.. "s".. " Data.")
end)

Any reason why it won’t save or won’t load the data?

Well, at first glance, your save data and load data prints happen at the end of the events, this will fire regardless if the game has saved or loaded.

That said, it’s hard to tell what the problem is exactly. Perhaps you can tell me what data equals when it loads

local data = playerData:GetAsync(player.UserId)
print(data)

It prints nil.

You aren’t using a pcall, so the print statement is only an indication that your code ran without issues, not that your DataStore calls were successfully performed. You should be sure to use pcalls when working with DataStore calls at nearly every opportunity.

The function connected to PlayerAdded may not run due to GetDataStore being a yielding function. The best case scenario for this is to assign the function to a variable, hook it to PlayerAdded and then call it for all existing players of the game. This will ensure that everything in terms of initialisation occurs.

Next huge problem is in relation to the way you’re creating values. Avoid using the parent argument if you’re setting properties immediately after creating an instance and try to consolidate where possible to lessen how much code you actually have to write out. Consider scalability and being able to handle arbitrary amounts of information.

And the cherry on top, my favourite nitpick against developers: use GetService to fetch services as opposed to using dot syntax. It is canonically correct and holds up consistency when working with services as you need to use GetService for a lot of them anyway.

Here is some code that incorporates my feedback accordingly. I have changed a few things that may interrupt how your DataStore workflow originally went, in regards to:

  • Spelling and naming conventions on code
  • Shortened a lot of bloat text for the DataStore
  • Generally focused on readability and scalability

(Code sample below, hidden for thread viewing convenience. It has been changed since initial posting to fix bugs and such.)

View code sample
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")

local DATA_VALUES = {
    "Rank", "Weapon", "Accessory1", "Accessory2",
    "Armor1", "Armor2", "Ability1", "Ability2",
    "Ability3", "Ability4", "Ability5", "Ability6"
}

local function playerAdded(player)
    -- Set parent of this after all child values are created
    local dataFolder = Instance.new("Folder")
    dataFolder.Name = "Data"

    -- Ditto
    local mainFolder = Instance.new("Folder")
    mainFolder.Name = "Main"

    for _, datumName in ipairs(DATA_VALUES) do
        local datum = Instance.new("StringValue")
        datum.Name = datumName
        datum.Parent = mainFolder
    end

    local success, playerData = pcall(function ()
        return PlayerDataStore:GetAsync(player.UserId)
    end)

    -- Came up a bit lazy on this part
    if success then
        if playerData then
            for key, value in pairs(playerData) do
                mainFolder[key].Value = value
            end
        else
            mainFolder["Rank"].Value = "F-"
        end
    else
        warn(("%s (%d)'s data could not be loaded!\n\t%s"):format(player.Name, player.UserId, playerData))
    end

    mainFolder.Parent = dataFolder
    dataFolder.Parent = player
end

local function playerRemoving(player) -- Consistency and organisation's sake
    -- No need to error handle: let this pass or fail organically
    local mainFolder = player.Data.Main
    local mainFolderContents = mainFolder:GetChildren()
    local data = table.create(#mainFolderContents)

    for _, datum in ipairs(mainFolderContents) do
        data[datum.Name] = datum.Value
    end

    local success, exception = pcall(function ()
        return PlayerDataStore:SetAsync(player.UserId, data)
    end)

    if not success then
        warn(("%s (%d)'s data was not saved!\n\t%s"):format(player.Name, player.UserId, exception))
    end
end

Players.PlayerAdded:Connect(playerAdded)
Players.PlayerRemoving:Connect(playerRemoving)

for _, player in ipairs(Players:GetPlayers()) do
    playerAdded(player)
end

When testing that your DataStore works by setting values directly from the Studio window, ensure that you are using the Server view and not the Client view. Changes from the client view will be simulated as the client making changes to the DataModel and will follow standard replication patterns (the change will not be received by the server). If you are testing it with game systems, then just play normally enough to receive data and you’re good to go.

2 Problems I fixed the red underlining and it still doesn’t work, second problem data is underlined??
image

Oh, replace that with “playerData”. I was thinking of the wrong variable there. I will change the code sample I linked above to reflect that fix.

Thats what I just did xd, testing now.

Still not working??


It’s also not printing the error message, sooo?
I am using server side aswell.

You’ll need to provide more information than “it doesn’t work”. Try to apply some basic debugging as well - while what I wrote may have seemed like a complete code sample, it’s mainly meant to be a code sample incorporating my feedback and obviously does not cover all points that it should in depth. I don’t normally recommend that developers directly copy and paste what I post to threads.

If an error message is not being sent to the console, that means that the code is working and that the source of error is in regards to how the game is fetching data. If you’d like, you can add a line below each pcall success check that prints out the result of the second variable (after success), which contributes to the aforementioned basic debugging efforts.

Mhm understood, I’ll add some prints around any see what I can figure out, thanks for your contribution and help.

It seems like it’s not saving correctly nor saving any of the values stored inside the folder. I have added a print function that printed “data[dataum.Value]” and all it resulted in was nil values. I also added a print function to print success and that was true all times so that part of the code was correct but when it printed “playerData” it resulted in nil meaning no data was saved there.

It seems like Roblox isn’t getting the value from folder, because every time I start I change the rank to “x+” for testing purposes and it never saves when I leave? Once again it prints nil 12 times.

Just doesn’t look like its working at all ;_;

image

1 Like

I’ll investigate the script and get back to you in a few moments with my results and a fixed sample. In the mean time, I suggest unmarking my solution (or keeping it if the information provided is of importance) in the instance that it pushes away other attempts to resolve the issue.

Thanks for reporting the issue to me. I was confident that my code sample worked but it seems that it may have met an err.

Hey there! I’ve already finished my investigation.

It so turns out that my keyboard was uncooperative at one point and I forgot to close the function running at the pcall! :sweat_smile: I noticed the red underline almost immediately after posting the code into a script. It also seems that I was using the wrong player variable!

The context menu can really help in situations where there’s an error and you want to quickly get to it if you can’t see it immediately. That’s usually one of my go-tos to check if I have any bugs in my code.

image

Here’s the code sample with applied fixes. It also includes a more detailed way of displaying pcall errors in the output: first a brief of the issue and then the exact error thrown by the script.

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")

local DATA_VALUES = {
    "Rank", "Weapon", "Accessory1", "Accessory2",
    "Armor1", "Armor2", "Ability1", "Ability2",
    "Ability3", "Ability4", "Ability5", "Ability6"
}

local function playerAdded(player)
    -- Set parent of this after all child values are created
    local dataFolder = Instance.new("Folder")
    dataFolder.Name = "Data"

    -- Ditto
    local mainFolder = Instance.new("Folder")
    mainFolder.Name = "Main"

    for _, datumName in ipairs(DATA_VALUES) do
        local datum = Instance.new("StringValue")
        datum.Name = datumName
        datum.Parent = mainFolder
    end

    local success, playerData = pcall(function ()
        return PlayerDataStore:GetAsync(player.UserId)
    end)

    -- Came up a bit lazy on this part
    if success then
        if playerData then
            for key, value in pairs(playerData) do
                mainFolder[key].Value = value
            end
        else
            mainFolder["Rank"].Value = "F-"
        end
    else
        warn(("%s (%d)'s data could not be loaded!\n\t%s"):format(player.Name, player.UserId, playerData))
    end

    mainFolder.Parent = dataFolder
    dataFolder.Parent = player
end

local function playerRemoving(player) -- Consistency and organisation's sake
    -- No need to error handle: let this pass or fail organically
    local mainFolder = player.Data.Main
    local mainFolderContents = mainFolder:GetChildren()
    local data = table.create(#mainFolderContents)

    for _, datum in ipairs(mainFolderContents) do
        data[datum.Name] = datum.Value
    end

    local success, exception = pcall(function ()
        return PlayerDataStore:SetAsync(player.UserId, data)
    end)

    if not success then
        warn(("%s (%d)'s data was not saved!\n\t%s"):format(player.Name, player.UserId, exception))
    end
end

Players.PlayerAdded:Connect(playerAdded)
Players.PlayerRemoving:Connect(playerRemoving)

for _, player in ipairs(Players:GetPlayers()) do
    playerAdded(player)
end

Let me know if this yields any success. I will also be updating the marked solution post with this code and making note that it was changed for future readers.

Thanks for your hard work but even after all these fixes and reworks roblox still wont save the one value i’m changing called “rank” and is printing nil 12 times.


image

image

I may go reference to my other datastores that work and use them…

My roblox must be acting weird, all my datatstores are not working??
Besides this one I made a while back:

local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("PlayerData")
local aLoaded = false

local Data = {
	Money = 0;
	Stand = "GoldExperienceRequiem";
}

game.Players.PlayerAdded:Connect(function(Player)
	local GrabbedData = PlayerData:GetAsync(Player.UserId, Data)
	wait(1)
	game.Players:WaitForChild(Player.Name):WaitForChild("Backpack"):WaitForChild("Data").Money.Value = GrabbedData.Money
	game.Players:WaitForChild(Player.Name):WaitForChild("Backpack"):WaitForChild("Data").Stand.Value = GrabbedData.Stand
	wait()
	aLoaded = true
	print("Client: ".. Player.Name.. " joined, loading Data")
end)

game.Players.PlayerRemoving:Connect(function(Player)
	local GrabbedMoney = Player.Backpack.Data.Money.Value
	local GrabbedStand = Player.Backpack.Data.Stand.Value
	wait()
	local Data = {
		Money = GrabbedMoney;
		Stand = GrabbedStand;
	}
	wait()
	PlayerData:SetAsync(Player.UserId, Data)
	print("Client: ".. Player.Name.. " leaving, saving Data")
end)

Just a P.S. preface before I begin, please try to edit posts when you need to include new information in brief sentences as opposed to adding more responses.

I just found out the issue: your test (or otherwise print statement) is flawed. During an iteration, you print against the newly created table, data, which starts off empty. You are also doing a table lookup using the data’s value as a key, which would definitely be nil. You instead need to write this:

print(datum, datum.Name, datum.Value)

If you want to check existence in the data folder after the key is added, move your print statement below the data set and run this:

print(data[datum.Name])

You should not get a nil value anymore, but instead a blank (due to no data held in the StringValue). Your data is saving and the script is functional, it’s just your test is bugged. Did you hop into a subsequent test session after changing the value and leaving to see if your data actually saved?

Off-topic meme, but relevant, so I included it for a humour factor in my post.

1 Like

Ok so apparently datastores don’t work in studio now ;_;


Thank you once again for your contribution and help with this post, very helpful.
also thanks for the tips on posting i’ll keep those in mind and use them on the future and
not to forget Gru.

And i’ll be reworking teh script as it’s messy and it annoys me xd.