Trouble with saving in Datastore script

I need to save the cookbooks that the player has bought in my game. When they collect a cookbook, it is a bool value added into the CookbooksCollected folder in the player, that works fine.
Loading the data works successfully, so I haven’t included that part of the script, but for some reason saving doesn’t work. It saved once, but never worked again, I didn’t make any changes either. There is an error message: “ServerScriptService.SavingCollectedBooks:73: attempt to index nil with 'CookbooksCollected”. I don’t really know what’s wrong with it, so I would really appreciate some help!

local DataStoreService = game:GetService("DataStoreService")
local collectedDataStore = DataStoreService:GetDataStore("collectedCookbooks")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CookbookList = ReplicatedStorage:WaitForChild("Cookbooks")


game.Players.PlayerRemoving:Connect(function(Player)

	--saving collected cookbooks
	local success, errormessage = pcall(function()
		local CollectedSave = {}

		for i, cookbook in pairs(Player.CookbooksCollected:GetChildren()) do

			if cookbook then
				table.insert(CollectedSave, cookbook.Name)
			end

		end

		collectedDataStore:SetAsync("User-"..Player.UserId, CollectedSave)

	end)
	if success then
		print("Data has been saved.")
	else
		print("Data has NOT been saved.")
		warn(errormessage)
	end


end)

game:BindToClose(function(Player)

	--saving collected cookbooks
	local success, errormessage = pcall(function()
		local CollectedSave = {}

		for i, cookbook in pairs(Player.CookbooksCollected:GetChildren()) do -- this is where the error message is.

			if cookbook then
				table.insert(CollectedSave, cookbook.Name)
			end

		end
		
		collectedDataStore:SetAsync("User-"..Player.UserId, CollectedSave)

	end)
	if success then
		print("Data has been saved.")
	else
		print("Data has NOT been saved.")
		warn(errormessage)
	end

end)

Thank you so much!

1 Like

Why do you use 2 functions to save the datas?

1 Like

im not sure if :BindToClose() carries a player parameter by default, that could be why cuz if it works for the first just fine, that means it doesnt know what the player is in the second function, however, the second function isnt probably needed unless if you’re shutting down, then thatd be fine but, you need to define the player in the BindToClose() somehow

The tutorial I was watching said to do one for player leaving and one for bind to close, incase Roblox’s servers shut down. Would just using player leaving work for both scenarios?

I’ll maybe remove the BindToClose function temporarily because I’m not actually sure which is running, I’ll see if the PlayerLeaving function works. I’ve done some research and I don’t think BindToClose actually has a player parameter, so I might loop through all the players in game and save the data that way, I’ll let you know how it goes.

It seems to work now, but I think it saved the data twice, and takes much longer for the play test to stop.
Here is a screenshot of the output, it seemed to save for both functions.

I put in this in the BindToClose function to see if this stopped the problem but now it doesn’t save at all, and no messages are printed, so I don’t really know.

	if game:GetService("RunService"):IsStudio() then
		return
	end

Is there any way I can stop this from happening, and fix this issue? Thanks!