Attempt to call a nil value when saving datastores

Hi, I have this script where it adds a value in players and then when the value is added or changes it saves. I’ve already tried printing out save texts so I know when it actually saves but when i re-test, the value doesn’t save. I’m a beginner so please don’t feed me

local DatastoreService = game:GetService("DataStoreService")

local dVersion = 1
local save = DatastoreService:GetDataStore("Coins "..dVersion)

game.Players.PlayerAdded:Connect(function(player)
	local previousData = save:GetAsync(player.UserId) -- Returns a number value.

	local coins

	if previousData ~= nil then
		coins = previousData
	else
		coins = 0
		save:SetAsync(player.UserId, 0)
	end

	local coinsValue = Instance.new("NumberValue", player)
	coinsValue.Name = "Currency"
	coinsValue.Value = coins
end)

game:BindToClose(function() -- Runs whenver the server is about to shut down/stop.
	print("STOPPED!")

	for i,player in pairs(game.Players:GetPlayers()) do
		local value = player.Currency.Value
		save:SetAsync(player.UserId, value)
		print("Saved data for "..player.Name)
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local value = player.Currency.Value

	if value ~= nil then
		print("Found data to save for "..player.Name.."!")
		save:SetAsync(player.UserId, value)
		print("Saved data for "..player.Name)
	else
		print("Did not manage to find data to save for "..player.Name.."!")
	end
end)

Which line is causing this error?

I’ve checked the console, it doesn’t specifically say which line

I think what could be going on here is that you are firing the :BindToClose() function before firing the PlayerRemoving function. The reasoning for this possible answer is because since :BindToClose() waits for the server to shutdown, the server shuts down before firing the PlayerRemoving function. Which causes the PlayerRemoving function to be nil. Try moving the BindToClose() function underneath the PlayerRemoving function and see if that changes anything.

How do I solve this, I’m new to lua sorry

1 Like
local DatastoreService = game:GetService("DataStoreService")

local dVersion = 1
local save = DatastoreService:GetDataStore("Coins "..dVersion)

game.Players.PlayerAdded:Connect(function(player)
	local previousData = save:GetAsync(player.UserId) -- Returns a number value.

	local coins

	if previousData ~= nil then
		coins = previousData
	else
		coins = 0
		save:SetAsync(player.UserId, 0)
	end

	local coinsValue = Instance.new("NumberValue", player)
	coinsValue.Name = "Currency"
	coinsValue.Value = coins
end)

game.Players.PlayerRemoving:Connect(function(player)
	local value = player.Currency.Value

	if value ~= nil then
		print("Found data to save for "..player.Name.."!")
		save:SetAsync(player.UserId, value)
		print("Saved data for "..player.Name)
	else
		print("Did not manage to find data to save for "..player.Name.."!")
	end
end)
-- Move the BindToClose function underneath the PlayerRemoving function 
game:BindToClose(function() -- Runs whenver the server is about to shut down/stop.
	print("STOPPED!")

	for i,player in pairs(game.Players:GetPlayers()) do
		local value = player.Currency.Value
		save:SetAsync(player.UserId, value)
		print("Saved data for "..player.Name)
	end
end)

Still get the error. This time, it took a bit longer to shutdown the test in studio

2 things I just noticed:

  1. You did not add a pcall function when saving the data. This is ESENTIAL when making data stores because if roblox’s data store servers are down, your script will break.

  2. This line maybe the one causing the issues:

This could be because nil isn’t a value for this (what I assume) NumberValue or IntValue. Here’s the fixed version of the saving function:

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

    local value = player.Currency.Value

	local success, err = pcall(function()
		save:SetAsync(player.UserId, value)
	end)
	
	if success then
		print("Successfully saved player's data!")
	else
		warn(err)
	end
end)

game:BindToClose(function()
	for i, player in pairs(game.Players:GetPlayers()) do
       local value = player.Currency.Value
		local success, err = pcall(function()
			save:SetAsync(player.UserId, value)
		end)

		if success then
			print("Successfully saved player's data!")
		else
			warn(err)
		end
	end
end)

I just edited the scripted, is this right?

local DatastoreService = game:GetService("DataStoreService")

local dVersion = 1
local save = DatastoreService:GetDataStore("Coins "..dVersion)

game.Players.PlayerAdded:Connect(function(player)
	local previousData = save:GetAsync(player.UserId) -- Returns a number value.

	local coins

	if previousData ~= nil then
		coins = previousData
	else
		coins = 0
		save:SetAsync(player.UserId, 0)
	end

	local coinsValue = Instance.new("NumberValue", player)
	coinsValue.Name = "Currency"
	coinsValue.Value = coins
end)

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

	local value = player.Currency.Value

	local success, err = pcall(function()
		save:SetAsync(player.UserId, value)
	end)

	if success then
		print("Successfully saved player's data!")
	else
		warn(err)
	end
end)

game:BindToClose(function()
	for i, player in pairs(game.Players:GetPlayers()) do
		local value = player.Currency.Value
		local success, err = pcall(function()
			save:SetAsync(player.UserId, value)
		end)

		if success then
			print("Successfully saved player's data!")
		else
			warn(err)
		end
	end
end)```

Can’t tell if that’s a typo or not. Otherwise, yes, the script looks correct now.

Still saying attempt to call a nil value…

Does this error happen when you run the game, or when you stop the game?

It happens when you run the test, I’ve also tried this in game too.

@vxsqi

i don’t see the parent and try this:

local dataStoreServise= game:GetService("DataStoreService")
local dversion=1
local dataStore=dataStoreServise:GetDataStore("coins"..dversion)

game.Players.PlayerAdded:Connect(function(plr)
	local coinsValue = Instance.new("NumberValue", plr)
	coinsValue.Name = "Currency"
  coinsValue.Parent=plr
  local id=plr.UserId
  local success, data=pcall(function()
    return dataStore:GetAsync(id)
  end)
  if success then
    if data then
      coinsValue.Value = data
      if data==nil then
        dataStore:SetAsync(id,0)
        coinsValue.Value = 0
      end
    else
      dataStore:SetAsync(id,0)
      coinsValue.Value = 0
    end
  else
    error("Connection error")
  end
end)
game.Players.PlayerRemoving:Connect(function(plr)
  local id=plr.UserId
  local currency= plr.Currency
  local success, data=pcall(function()
    dataStore:SetAsync(id,currency.Value)
  end)
  if success then
    print("successfully saved "..currency.Value.." to player "..plr.Name)
  else
    warn("couldn't save data")
  end
end)

Forgot to mention, there’s another script that adds cash every 1 second and now I’m not getting any cash

were you adding cash to the leader stats or something

actually the saving part should work fine with this script

can you show that script as well?

It’s a numbervalue in players. It’s not to leaderstats

local value = player.Currency.Value

if you have something like this then change to:
local value = player.Currency
value.Value=value.Value+1

sorry i just fixed it, there were two values, but again the values arent saving

script for adding the currency. these two are separate scripts

game.Players.PlayerAdded:Connect(function(player)
	local value = Instance.new("NumberValue", player)
	value.Name = "Currency"
	
	
	while wait(1) do
		value.Value = value.Value + 25
	end
end)```