DataStore SetAsync not working

Oh and surprisingly, it’s working in-game. So, this is a Studio related bug or error…

1 Like

You can save tables as a DataStore value and you don’t need to JSONEncode or JSONDecode the values as it is automatically done for you.

I organized the code a little. This should work.

Pets = game:GetService("DataStoreService"):GetDataStore("Pets")

game.Players.PlayerAdded:Connect(function(player)
	local petsval = Pets:GetAsync(player.userId)
	print(petsval)
end)

game.Players.PlayerRemoving:Connect(function(player)
	Pets:SetAsync(player.userId, "NormalPet")
end)

Is Studio Access to API Services enabled?

If it was not enabled it would provide an error, but in OPs case that does not seem to be the case. It seems to return nil, meaning that the GetAsync call is working.

2 Likes

I can confirm I am having the same issue. The line before the SetAsync part in my script will print, but the line after it won’t print and my data wont save. Really annoying bug.

5 Likes

If you create a post about it, I guarantee others will see and try to do their best to help.

I’ve already had people try to help me on Discord plus I have tested it on multiple games (including completely new places) and the same issue still occurs.

1 Like

When the player leaves, the server closes before the data gets saved. You will have to use BindToClose to save the data before the server shutdowns. Check out this post that explains how to save data properly.

1 Like

Still doesn’t work. Currently impossible to play test in studio atm. Thank you for the suggestion though

2 Likes

Yeah, that is a Roblox issue at the moment. Try it in a live game and it should work. Also you should have a loop that saves data every minute. Check out this article Documentation - Roblox Creator Hub

If you want me to look over the code, send me a message and I’ll do my best to help.

I Know this is like 20 days ago but i had the same issue with that and the Studio/Server was force closing to fast and it would cancel any scripts running in that time and if the data has not requested to save then you get data loss but Adding this to your data script will make sure that if server is shutdown it will kick everyone then wait 10 seconds then close the server if your in studio it will disconnect your client then wait 3 second to close the server.

The code:

game:BindToClose(function()
if not RunService:IsStudio() then
local Aplayers = Players:GetPlayers()
for i = 1,#Aplayers do
Aplayers[i]:Kick(“Server is shutting down: Please rejoin, your data will be saved.”)
end
wait(10)
else
wait(3)
end
end)

It took me forever to find this out hope it helps

the working code:

game:BindToClose(function()
if not RunService:IsStudio() then
for v, i in next, game.Players:GetPlayers()) do
i:Kick(“Server is shutting down: Please rejoin, your data will be saved.”)
end
wait(10)
else
wait(3)
end
end)

Those waits are pointless. The server will close down the moment your operations finish, they don’t stall how long the server stays up for.

Don’t kick every player from the server from BindToClose: not only is this not the intended use of BindToClose, but it is also grossly unnecessary because all players will already be gone from the server. You should instead implement data saving techniques for leftover data sets that the server still tracks.

As well, two things about your loop:

  • While what variable names you use for the for loop don’t quite matter, you have the standard variable convention in reverse. The i should come first as it stands for index.

  • Where did people learn this unreadable way of writing for loops with in next? Use a proper generator. GetPlayers returns an array, so use ipairs to iterate over it.

4 Likes

Has anyone noticed “player.userId”. userId is supposed to be capitilised right? player.UserId…? Correct me if I’m wrong.

userId is deprecated in favour of UserId for the sake of naming convention consistency. All properties follow PascalCase convention and their camelCase variants are deprecated. Yes UserId should be capitalised but in the sense that you’re using the current correct property rather than the old one.

So I’ve had this problem before! The way to do this is instead of leaving the game in-studio, you have to kick the player from the game in the command line.

This is because in the studio, when you leave/stop the game, the server and the client shutdown at the same time! This is a problem because if the server shuts down before saving the data won’t save!

If you kick the player instead, the server is still running because the player still has that kicked message. That’s why the server is able to save the data!

Heres the line you should write in the client’s command line in the studio

game.Players.LocalPlayer:Kick()
6 Likes

Hey did you ever fix this problem I am currently having it too just like you in studio it doesnt work most of the time but in game it does work?

I don’t remember if I ever fixed this particular issue but it’s probably best to use something like ProfileService for data saving because it handles all the edge-cases for you.

The problem that I could see is it needed to save to a boolValue or something for it to setAsync.

local DataStoreService = game:GetService("DataStoreService")
local PetDataStore = DataStoreService:GetDataStore("Pets")

game.Players.PlayerAdded:Connect(function(player)
	local success, petData = pcall(function()
		return PetDataStore:GetAsync(player.UserId)
	end)

	if success then
		local boolVal = Instance.new("BoolValue", player)
		boolVal.Name = "Pet"
		boolVal.Value = petData or "normalPet"
	else
		warn("Failed to retrieve pet data for player " .. player.Name)
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local boolVal = player:FindFirstChild("Pet")

	if boolVal then
		local success, err = pcall(function()
			PetDataStore:SetAsync(player.UserId, boolVal.Value)
		end)

		if not success then
			warn("Failed to save pet data for player " .. player.Name .. ": " .. err)
		end
	end
end)