Attempt to index number with 'TotalKills'

  1. What do you want to achieve? Keep it simple and clear!
    Save TotalKills Data To Player ID

  2. What is the issue? Include screenshots / videos if possible!
    ServerScriptService.Main.PlayerData:47: attempt to index number with ‘TotalKills’ - Server - PlayerData:47

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    Devfourms and videos online with data storage using

Code:

--// REMOTES \\--

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetDataStore("2")

local PlayerDataStorage = ReplicatedStorage:FindFirstChild("PlayerDataStorage")
local PlayerTemplate = PlayerDataStorage:FindFirstChild("TemplateFolder")

local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")
local sessionData = {}

--// FUNCTIONS \\--

Players.PlayerAdded:Connect(function(player)
	--Create new Player profile
	local newProfile = PlayerTemplate:Clone()
	newProfile.Name = player.Name
	newProfile.Value = player.UserId
	newProfile.Parent = PlayerDataStorage
	
	local totalKillsData = newProfile.Data.TotalKills.Value
	
	local success, playerData = pcall(function()
		return PlayerDataStore:GetAsync(player.UserId)
	end)
	
	if success then
		print("Data loaded: " .. player.Name)

		if not playerData then
			print("New player, giving default data")

			playerData = {
				["TotalKills"] = 0,
			}
		end

		sessionData[player.UserId] = playerData
	else
		warn("Couldn't load data for: " .. player.Name)
		player:Kick("Couldn't load your data, rejoin")
	end

	totalKillsData.Value = sessionData[player.UserId].TotalKills
end)

Players.PlayerRemoving:Connect(function(player)
	local playerProfile = PlayerDataStorage:FindFirstChild(player.Name)

	--Save Player data
	if playerProfile then
		--Save Player data
		--PlayerDataStore:SetAsync(player.UserId, playerProfile.Data.TotalKills.Value)
		--PlayerDataStore:SetAsync(player.UserId, playerProfile.Data.TotalDeaths.Value)

		--Remove Player profile
		playerProfile:Destroy()
	end
end)

image

GlobalDataStore:SetAsync associates one key with one value. Subsequent calls to this function will override the previous value. Since the last value you set to the player’s key was TotalDeaths.Value, that will now be what is receive by your GlobalDataStore:GetAsync call. The schema your data-loading code is expecting Vs. the schema set by your data-saving code is in conflict. Your data-loading code expects the schema:

{
    TotalKills: number
}

While the real data is just TotalDeaths.Value—a number. This is why when your data-loading code goes to access the “TotalKills” key of an expected table, you instead get the error "attempt to index number with ‘TotalKills’. You need to update your data-saving code to adhere to the expected schema:

local data = {
    TotalKills = playerProfile.Data.TotalKills.Value,
    -- ...
}

playerDataStore:SetAsync(player.UserId, data)

P.S. sessionData is redundant. You can remove it from your code

2 Likes

In addition to the above, you should add a return here

return player:Kick("Couldn't load your data, rejoin")

Why? After the player is kicked, the game will try to obtain the data and give the same error. It’s not really very important, but this way the console doesn’t get filled with errors.

1 Like

After adding your code and tinkering around. There are no errors of the sorts, which is great and all but no data is saving. I think i missed something. Could you check this out for me?

--// REMOTES \\--

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetDataStore("2")

local PlayerDataStorage = ReplicatedStorage:FindFirstChild("PlayerDataStorage")
local PlayerTemplate = PlayerDataStorage:FindFirstChild("TemplateFolder")

local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")

--// FUNCTIONS \\--

Players.PlayerAdded:Connect(function(player)
	--Create new Player profile
	local newProfile = PlayerTemplate:Clone()
	newProfile.Name = player.Name
	newProfile.Value = player.UserId
	newProfile.Parent = PlayerDataStorage
	
	local data = {
		TotalKills = newProfile.Data.TotalKills.Value,
		-- ...
	}

	PlayerDataStore:SetAsync(player.UserId, data)
	
	local success, playerData = pcall(function()
		return PlayerDataStore:GetAsync(player.UserId)
	end)
	
	if success then
		print("Data loaded: " .. player.Name)

		if not playerData then
			print("New player, giving default data")

			playerData = {
				["TotalKills"] = 0,
			}
		end
	else
		warn("Couldn't load data for: " .. player.Name)
		return player:Kick("Couldn't load your data, rejoin")
	end
end)

Players.PlayerRemoving:Connect(function(player)
	local playerProfile = PlayerDataStorage:FindFirstChild(player.Name)

	--Save Player data
	if playerProfile then
		--Save Player data
		

		--Remove Player profile
		playerProfile:Destroy()
	end
end)

PS: Thanks alot for helping me out