Datastore Service issue, no data is saved when the player exits

Sorry for the mistakes (English is not my first language)
In my RPG game, the player can
place various items, when the player exits, they should be saved, but this does not happen.
All placed blocks are in the folder.
The main problem:
When the last player leaves, his data is not saved.

	local Data_Values = player:WaitForChild("MainData")
	local Data_Blocks = workspace.PlayersBlocks:WaitForChild(player.UserId)
	local Values_table = DataModule.Encrypt(Data_Values:GetChildren())
	local Blocks_table = DataModule.Encrypt(Data_Blocks:GetChildren(),1)
	local Data = {
		['Blocks'] = Blocks_table;
		['Values'] = Values_table;
	}
	print(Data)
	
	repeat
		Datastore:UpdateAsync(tostring(player.UserId),function(OldValue)
			if Data then
				return Data
			else
				return OldValue  
			end
		end)
		wait()
		print("Retry")
	until Datastore:GetAsync(tostring(player.UserId))
	
	Datastore:UpdateAsync(tostring(player.UserId),function(OldValue)
		if Data then
			return Data
		else
			return OldValue  
		end
	end)
	if workspace.PlayersBlocks:FindFirstChild(player.UserId) then
		workspace.PlayersBlocks[player.UserId]:Destroy()
	end
	if game.ReplicatedStorage.SkyblockInv:FindFirstChild(player.UserId) then
		game.ReplicatedStorage.SkyblockInv[player.UserId]:Destroy()
	end
	wait(GameRules.Rules["Waiting data Timeout"])
end
Players.PlayerRemoving:Connect(function(player)
	SavePlayerData(player)
end)

player.MainData - Values folder
DataModule.Encrypt - Turns Instance into a table

PlayerRemoving works if the server is not going to shut down(more than 1 player) if you’re testing it with only one player it wont work as the server is shutting down and the data wont save in time so you have to add another event called game:BindToClose() and save the data in there aswell.

example:

game:BindToClose(function()
    for i, player in pairs(game.Players:GetPlayers()) do
        SavePlayerData(player)
    end
end)

Why are you having UpdateAsync called on a repeat loop? You should only run it once, and you don’t need to run GetAsync to make sure the data is saved.

In this case you can really just delete that whole repeat until block. Calling that many data store functions (at least 3 times per leaving player) will eat a chunk out of your data store budget.

local Success, Data = pcall(function()
    return Datastore:UpdateAsync(etc)
end)

With the above code, follow it up with print(Success, Data). If it displays true and then the table you intended to save, it worked. If it never prints at all then the issue occurs before the UpdateAsync call. If you want to actually view the prints, make sure you use a local studio server and view the output in the server window.

I added a loop as I experimented. This was not the case before, but the problem remains the same.

local SavePlayerData = function(player)
	local Data_Values = player:WaitForChild("MainData")
	local Data_Blocks = workspace.PlayersBlocks:WaitForChild(player.UserId)
	local Values_table = DataModule.Encrypt(Data_Values:GetChildren())
	local Blocks_table = DataModule.Encrypt(Data_Blocks:GetChildren(),player:WaitForChild("IslandPosition").Value)
	local Data = {
		['Blocks'] = Blocks_table;
		['Values'] = Values_table;
	}
	print(Data)
	
	Datastore:UpdateAsync(tostring(player.UserId),function(OldValue)
		if Data then
			return Data
		else
			return OldValue  
		end
	end)
	
	if workspace.PlayersBlocks:FindFirstChild(player.UserId) then
		workspace.PlayersBlocks[player.UserId]:Destroy()
	end
	if game.ReplicatedStorage.SkyblockInv:FindFirstChild(player.UserId) then
		game.ReplicatedStorage.SkyblockInv[player.UserId]:Destroy()
	end
	wait(GameRules.Rules["Waiting data Timeout"])
end
Players.PlayerRemoving:Connect(function(player)
	SavePlayerData(player)
end)
game:BindToClose(function()
	for i, v in pairs(game.Players:GetPlayers()) do
		SavePlayerData(v)
	end
	wait(10)
end)

But it still doesn’t work

Whats the wait for?
Is “SavePlayerData” an actual function in your script?
It was just an example you can adjust whats in the for loop according to your code.

wait(10)?
I assumed that due to the shutdown of the server, UpdateAsync simply did not have time to save data
In the studio, the script works

Is there any errors? did you do any debugging to see what goes wrong in the script?

The above describes how this function works.

I know how your script works im asking if you did any debugging, did you check your modules and what they return to see if they’re even sending back data

	print(Data)
	Datastore:UpdateAsync(tostring(player.UserId),function(OldValue)
		if Data then
			return Data
		else
			return OldValue  
		end
	end)

image
For this, print (Data)

Try using :SetAsync() to see if the issue is with your script or how you’re using update async, you can change back to updateAsync if thats not the case.

but, when loading data, it turns out that datastore = nil
I have tried SetAsync ()

I dont want to keep bumping this post over and over again, do you have discord? we can talk it out there instead of on the forum if you dont mind.

I now have no opportunity to communicate in discord (I’m not at home)

The problem is that the data is saved in the studio, it is saved if you exit the game, but the data is not saved if you are left 1 on the server

The player instance is destroyed a few frames after they have left you should instead store their UserId in a variable and save with that.

Could the problem be that: SetAsync () fires 5 seconds after the player has left the server?

As I have said, it’s likely because the player has left by the time you try to save the data meaning their UserId is nil.