Attempt to index nil while adding a id to table.Array

  1. What do you want to achieve? Keep it simple and clear!
    So i’m making an chance system, which use exact table.Array to store amount and name. By default table.Array is
local success, data = LoadData(player)
	sessionData[player.UserId] = success and data or {
		Power = 0,
--Main Array
		LuckAmounts = {
			
		}
--End of MainArray	
}
  1. What is the issue? Include screenshots / videos if possible!
    It sends me nil error about id

    from this code
function PlayerManager.AddLuck(player, id)
	local data = sessionData[player.UserId]
   print(id)
	if not table.find(data.LuckAmounts, id) then
		table.insert(data.LuckAmounts, id)
	end
end

seems like id is nil, but when i print it it says "Gen1"same as it should do
3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I tryed to use few checks for id, but idk why that happens, also wait because was thinking what array is nil

Here is code where everything get’s added:

local ChancesModule = require(game:GetService("ServerScriptService").MainModules.ChanceModule)
local Players = game.Players
local PlayerManager = require(game:GetService("ServerScriptService").PlayerManager)
local LuckTrigger = workspace:FindFirstChild("RemoteEvents"):FindFirstChild("LuckTrigger")
local function GetRandomGenSet(player)
	for genName, odds in pairs(ChancesModule) do
		if math.random() < 1/odds then
			print(genName)
			PlayerManager.AddLuck(player, genName)
			local LuckTable = PlayerManager.GetLuckAmounts(player)
			print(LuckTable)
			if table.find(LuckTable, genName) then
				if odds >= 1 then
					LuckTable.genName.Value += 1 * (odds/10)
				elseif odds < 1 then
					LuckTable.genName.Value += 1
				end
			LuckTrigger:FireClient(player, LuckTable)
			end
		end
	end
end
 
local function InfiniteCall(player)
		GetRandomGenSet(player)
	task.wait(1)
	InfiniteCall()
end

Players.PlayerAdded:Connect(function(plr)
	print("Plr Added")
	plr.CharacterAdded:Connect(function(Char)
		print("Char Added")
		local pHead = Char:FindFirstChild("Head")
		if pHead:FindFirstChild("AdvancedGameGUI") then
			InfiniteCall(plr)
			print("Advanced GUI Found")
			
		--[[else
			if pHead:WaitForChild("AdvancedGameGUI") then
				InfiniteCall(plr)
			end]]--
		end
	end)
	end)

Probably has to do with the LoadData function. Success isn’t returning false or nil so the player session data is becoming the nil variable data. That, or you require the module from different scripts which will reset the data. You can fix this with BindableFunctions to get the variable from the main script.

it is not, that script used in a different games with similiar params and function, everything commented is not usable in this game, but those should work fine. Here is same script from different game

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("PlayerData")
local MarketplaceService = game:GetService("MarketplaceService")
local Gamepasses = require(script.Parent.Gamepasses)
local BanHammerId = 67822412 
local RainbowCarpetId = 67822809
local SparklingSwordId = 67823158
local BadgeHandlerEvent = workspace.Events.BadgeHandlerEvent
local DonateStuffFolder = game:GetService("ServerStorage").DonateStuff
local function LeaderboardSetup(value)
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	local Cash = Instance.new("NumberValue")
	Cash.Name = "Cash"
	Cash.Value = value
	Cash.Parent = leaderstats
	return leaderstats
end

local function LoadData(player)
	local success, result = pcall(function()
		print("Data Loading...")
		return PlayerData:GetAsync(player.UserId)
	end)
	if not success then
		warn("LOADING DATASTORE ERROR, PLEASE FIX IT")
	end	
	return success, result
end

local function SaveData(player, data)
	local success, result = pcall(function()
		print("Data Saving...")
		PlayerData:SetAsync(player.UserId, data)
	end)
	if not success then
		warn("SAVING DATASTORE ERROR, PLEASE FIX IT")
	end
	return success
end

local sessionData = {}

local playerAdded = Instance.new("BindableEvent")
local playerRemoving = Instance.new("BindableEvent")

local PlayerManager = {}

PlayerManager.PlayerAdded = playerAdded.Event
PlayerManager.PlayerRemoving = playerRemoving.Event
function PlayerManager.Start()
	for _,player in ipairs(Players:GetPlayers()) do
		coroutine.wrap(PlayerManager.OnPlayerAdded)(player)	
	end

	Players.PlayerAdded:Connect(PlayerManager.OnPlayerAdded)	
	Players.PlayerRemoving:Connect(PlayerManager.OnPlayerRemoving)	

	game:BindToClose(PlayerManager.OnClose)
end

function PlayerManager.OnPlayerAdded(player)
	PlayerManager.RegisterGamepasses(player)
	PlayerManager.RegisterDonateStuff(player)
	BadgeHandlerEvent:Fire(player, 2129182596)
	player.CharacterAdded:Connect(function(character)
		PlayerManager.OnCharacterAdded(player, character)
	end)

	local success, data = LoadData(player)
	sessionData[player.UserId] = success and data or {
		Cash = 0,
		UnlockIds = {}
	}
	local leaderstats = LeaderboardSetup(PlayerManager.GetMoney(player))
	leaderstats.Parent = player

	playerAdded:Fire(player)
end

function PlayerManager.OnCharacterAdded(player, character)
	local humanoid = character:FindFirstChild("Humanoid")
	if humanoid then
		humanoid.Died:Connect(function()
			wait(1)
			player:LoadCharacter()
		end)
	end
end

function PlayerManager.GetMoney(player)
	return sessionData[player.UserId].Cash
end

function PlayerManager.SetMoney(player, value)
	if value then
		sessionData[player.UserId].Cash = value
		local leaderstats = player:FindFirstChild("leaderstats")
		if leaderstats then
			local Cash = leaderstats:FindFirstChild("Cash")
			if Cash then
				Cash.Value = value
			end
		end	
	end
end

function PlayerManager.AddUnlockId(player, id)
	local data = sessionData[player.UserId]
	
	if not table.find(data.UnlockIds, id) then
		table.insert(data.UnlockIds, id)
	end
end

function PlayerManager.GetUnlockIds(player)
	return sessionData[player.UserId].UnlockIds
end

function PlayerManager.OnPlayerRemoving(player)
	SaveData(player, sessionData[player.UserId])
	playerRemoving:Fire(player)
end

function PlayerManager.OnClose()	
	for _, player in ipairs(Players:GetPlayers()) do
		coroutine.wrap(PlayerManager.OnPlayerRemoving(player))()
	end
end

function PlayerManager.RegisterDonateStuff(player)
	if MarketplaceService:UserOwnsGamePassAsync(player.UserId, BanHammerId) then
		local BanHammer = DonateStuffFolder:FindFirstChild("BanHammer")
		local BanHammerClone1 = BanHammer:Clone()
		BanHammerClone1.Parent = player.Backpack
		local BanHammerClone2 = BanHammer:Clone()
		BanHammerClone2.Parent = player.StarterGear
	end
	if MarketplaceService:UserOwnsGamePassAsync(player.UserId, RainbowCarpetId) then
		local RainbowCarpet = DonateStuffFolder:FindFirstChild("RainbowCarpet")
		local RainbowCarpetClone1 = RainbowCarpet:Clone()
		RainbowCarpetClone1.Parent = player.Backpack
		local RainbowCarpetClone2 = RainbowCarpet:Clone()
		RainbowCarpetClone2.Parent = player.StarterGear
	end
	if MarketplaceService:UserOwnsGamePassAsync(player.UserId, SparklingSwordId) then
		local SparklingSword = DonateStuffFolder:FindFirstChild("SparklingSword")
		local SparklingSwordClone1 = SparklingSword:Clone()
		SparklingSwordClone1.Parent = player.Backpack
		local SparklingSwordClone2 = SparklingSword:Clone()
		SparklingSwordClone2.Parent = player.StarterGear
	end
end
function PlayerManager.RegisterGamepasses(player)
	for id, passFunction in pairs(Gamepasses) do
		if MarketplaceService:UserOwnsGamePassAsync(player.UserId, id) then
			passFunction(player)
		end
	end
end

return PlayerManager

also if it would be nil it would print

warn("LOADING DATASTORE ERROR, PLEASE FIX IT")

Then you probably have an empty table saved in your personal datastore. Have you tried printing the data after calling LoadData?

Wait a bit please, playermanager randomly got deleted somehow idk, so need to rewrite it again


Printed out success table

So it’s getting something… From what I can see, when PlayerManager.AddLuck() is being called, sessionData[player.UserId] does not exist yet. Maybe you call it before properly loading player data? You can get around that easily by converting your dot syntax to colon syntax (. to : ) and returning self. That way, you can do things like PlayerManager:Start():AddLuck(Player, 10).

Example:

local PlayerManager = {};

function PlayerManager:Start()



   self.__dataTable = {};
   setmetatable(self.__dataTable,{ __newindex = function(t,k,v) rawset(t,k,v) print(" Player added to data table.") });
   function self.__dataTable:Add(index, val)
     self[index] = val;
   end

   function self.__dataTable:Update(player, index, newVal)
    return self.__dataTable[player] ~= nil and pcall(self.__dataTable.Add, self, player[index], newVal);
   end

   local function OnPlayerAdded(Player)
    self.__dataTable:Add(Player.UserId, LoadData(Player))
   end

   local function OnPlayerRemoving(Player)
    SaveData(Player);
   end

   for i,v in pairs(Players:GetPlayers()) do 
     OnPlayerAdded(v);
   end


   game:BindToClose(function() for i,v in pairs(Players:GetPlayers()) do OnPlayerRemoving(v) end end);
   return self;
end

function PlayerManager:AddLuck(Player, amount)
  self.__dataTable:Update(player, "Luck", amount);
  return self;
end

return PlayerManager

Exactly what could i say, i was thinking about that, i added task.wait(5),task.wait(10) to script where LuckAdd getting called and it literally was giving same result as without task.wait, data 100% loaded in 10 seconds

EDIT: Plus script where LuckAdd being called is too being called after CharacterAdded same as DS one, so i’m sure it have time to load correctly

EDIT:Also tryed giving even more time, but after 30,60 and etc. seconds happens same.

CharacterAdded doesn’t yield the script. If you want it to yield, you have to use CharacterAdded:Wait().

isn’t this same?

plr.CharacterAdded:Connect(function(Char)

image
Like it is wait 2 seconds before character load, so i assume it works

EDIT: Ohh you are talking about DS script, i’m just dumb, well anyways so, data should be loaded in 30+ seconds, so problem not in data load

Yeah, but you don’t load the data at all in that function anywhere. You don’t call PlayerManager anywhere in your PlayerAdded, and InfiniteCall triggers the luck system. Since PlayerManager isnt called in the PlayerAdded, the table is never generated.

Wait… Duh i’m dumb i forgot to add Server script to call PlayerManager, i’m idiot

Forgot those 2 lines…

local PlayerManager = require(script.Parent.PlayerManager)

PlayerManager.Start()

Yeah it fixed that error, but now in lines 14-16 happens this
image

if odds >= 1 then
					LuckTable.genName.Value += 1 * (odds/10)
				elseif odds < 1 then
					LuckTable.genName.Value += 1
				end

LuckTable.genName is nil, you probably forgot to add it in the LuckTable somewhere.

Well i use those lines to add genName first to table and then only give it a value

PlayerManager.AddLuck(player, genName)
			local LuckTable = PlayerManager.GetLuckAmounts(player)
			print(LuckTable)
			if table.find(LuckTable, genName) then
				if odds >= 1 then
					LuckTable.genName.Value += 1 * (odds/10)
				elseif odds < 1 then
					LuckTable.genName.Value += 1
				end

It’s not there so maybe you forgot to add the lines?

It works fully with player manager functions, and they get data, as in script firstly Luck if it is not in table already get’s added to table

function PlayerManager.AddLuck(player, id)
	local data = sessionData[player.UserId]

	if not table.find(data.LuckAmounts, id) then
		table.insert(data.LuckAmounts, id)
	end
end

And then it gets an new luck table by this code

function PlayerManager.GetLuckAmounts(player)
	return sessionData[player.UserId].LuckAmounts
end

And then get’s gen name, in example it is Gen1 and it name will match to Name in Array.

Maybe that because when i’m adding it first time i don’t add any value to it?

EDIT: By default that script was used in tycoon where id is an number like “1542354” and there it is string, so i defenitely need to make it like that “Gen1 = 0” as i understand if it will just add “Gen1” i can’t add it to value, but idk how to add value to it