Attempt to index nil [Nobody helping, please help]

script is not working for some reason.
keeps giving me error message, any help?

ServerScriptService.Data:117: attempt to index nil with 'Bomb'

script:

local Mastery = {
	"Ember Jujitsu",
	"Inferno Jujitsu",
	"Aquatic Fists",
	"Waterstream Fists",
	"Katana",
	"Test",
	"Bomb",
	"Smoke",
	"Ice",
	"Chop",
	"Flame"
}

	local AllMastery = Instance.new("Folder")
	AllMastery.Name = "Masteries"

	temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

	if typeof(temporalData[plr.UserId].Mastery) ~= "table" then
		temporalData[plr.UserId].Mastery = {}
	end

	for _, Masteryy in ipairs(Mastery) do
		if temporalData[plr.UserId].Mastery[Masteryy] == nil or 0 then
			temporalData[plr.UserId].Mastery[Masteryy] = 1
		end
		local bool = Instance.new("NumberValue")
		bool.Name = Masteryy
		bool.Value = temporalData[plr.UserId].Mastery[Masteryy]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].Mastery[Masteryy] = bool.Value ]---------- bug
		end)
		bool.Parent = AllMastery
	end

	AllMastery.Parent = plr
2 Likes

Can you test it with other values?

1 Like

It works, but for numbervalue & intvalue no. It works for boolvalue & stringvalue

Which line is throwing the error?

temporalData[plr.UserId].Mastery[Masteryy] = bool.Value ]---------- bug

Masteryy is a string. If temporalData[plr.UserId].Mastery is anything like the dictionary at the top of the script, then indexing with a string is always going to return nil.

local a = {Apples=7,Time=0}
local d = {"Index1","Test"}

--a[1] is equivalent to a.Apples and a["Apples"], and returns 7
--However d only takes integers as indexes because the values aren’t assigned an index, so the default is indices are (1…-1).

how do i input this into my table?

In your case, you can just use the _ variable (index returned by pairs() / ipairs()) instead of Masteryy

im kinda dumb so i dont understand what you just said

local Mastery = {
	"Bomb", 0
}

like that?

More like

local Mastery = {
      Bomb=false, --or ["Bomb"] = false
      Ice=true,
}

In your script, you don’t have to change the Mastery table. I would recommend just using the index instead of the value (in the ipairs() index:pair loop)
Like book.Value = temporalData[plr.UserId].Mastery[_]

im actaully super confused and i dont know what to do can you explain further more because i have to go soon

	for _, Masteryy in ipairs(index:pair loop) do
		if temporalData[plr.UserId].Mastery[Masteryy] == nil or 0 then
			temporalData[plr.UserId].Mastery[Masteryy] = 1
		end
		local bool = Instance.new("NumberValue")
		bool.Name = Masteryy
		print(Masteryy)
		bool.Value = temporalData[plr.UserId].Mastery[0]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].Mastery[0] = bool.Value
		end)
		bool.Parent = AllMastery
	end

are you still there…?? i still dont understand…

if temporalData[plr.UserId].Mastery[Masteryy] == nil or 0 then

This always evaluates to true, it should be

if temporalData[plr.UserId].Mastery[Masteryy] == nil or temporalData[plr.UserId].Mastery[Masteryy] ==  0 then

This is probably not causing the error but its still an issue

Okay, but the problem is solved, i just don’t know what to do.
Kaz said

" In your script, you don’t have to change the Mastery table. I would recommend just using the index instead of the value (in the ipairs() index:pair loop)
Like book.Value = temporalData[plr.UserId].Mastery[_]"

But i do not understand what he means

I think the reason we cant help you as you would like is because your code is very ambiguous. You probably don’t want to implement his suggestion, as the indexes of your masteries may change if you add or remove any, The way you have it now works, but I do suggest you change your implementation.

How would i change it? Because this is needed

I cant really say how you should change it because I know nothing of your code base and how changes will affect other scripts. I suggest you make a module script for saving/loading data and not using value objects at all. In addition to that you can move global information into module scripts so it can be accessed anywhere, like your mastery table. Right now if a separate script wants to access the masteries you would need to just copy and paste that table into it, and any change you make would have to be made in every script.

It is all just personal preference so you should ultimately do what helps you further development without future roadblocks.

well this sucks. i’m geniuelly stucked and the other guy decided to leave me on a cliffhanger.

Full script for anybody who could help.

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local isStudio = RunService:IsStudio()
local DataStoreService = game:GetService("DataStoreService")
local ds = DataStoreService:GetDataStore("LeaderStatSave")

local temporalData = {}

local FightingStyles = {
	"Ember Jujitsu",
	"Inferno Jujitsu",
	"Aquatic Fists",
	"Waterstream Fists",
	"Sliver Claws",
	"Midas Claws"
}
local Swords = {
	"Katana",
	"",
	"Samurai",
	"Leader",
	"Witch",
	"Divine"
}
local Mastery = {
	"Ember Jujitsu",
	"Inferno Jujitsu",
	"Aquatic Fists",
	"Waterstream Fists",
	"Katana",
	"Test",
	"Bomb",
	"Smoke",
	"Ice",
	"Chop",
	"Flame"
}
local StoredFruits = {
	"Bomb",
	"Smoke",
	"Ice",
	"Chop",
	"Flame"
}


Players.PlayerAdded:Connect(function(plr)
	local AllSwords = Instance.new("Folder")
	AllSwords.Name = "Swords"
	
	temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

	if typeof(temporalData[plr.UserId].Swords) ~= "table" then
		temporalData[plr.UserId].Swords = {}
	end

	for _, sword in ipairs(Swords) do
		if temporalData[plr.UserId].Swords[sword] == nil then
			temporalData[plr.UserId].Swords[sword] = false
		end
		local bool = Instance.new("BoolValue")
		bool.Name = sword
		bool.Value = temporalData[plr.UserId].Swords[sword]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].Swords[sword] = bool.Value
		end)
		bool.Parent = AllSwords
	end

	AllSwords.Parent = plr
	
-------------------------------------------------------------------------------------
	
	local AllFightingStyles = Instance.new("Folder")
	AllFightingStyles.Name = "Fighting Styles"

	temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

	if typeof(temporalData[plr.UserId].FightingStyles) ~= "table" then
		temporalData[plr.UserId].FightingStyles = {}
	end

	for _, FightStyle in ipairs(FightingStyles) do
		if temporalData[plr.UserId].FightingStyles[FightStyle] == nil then
			temporalData[plr.UserId].FightingStyles[FightStyle] = false
		end
		local bool = Instance.new("BoolValue")
		bool.Name = FightStyle
		bool.Value = temporalData[plr.UserId].FightingStyles[FightStyle]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].FightingStyles[FightStyle] = bool.Value
		end)
		bool.Parent = AllFightingStyles
	end

	AllFightingStyles.Parent = plr
	
-------------------------------------------------------------------------------------
	
	local AllMastery = Instance.new("Folder")
	AllMastery.Name = "Masteries"

	temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

	if typeof(temporalData[plr.UserId].Mastery) ~= "table" then
		temporalData[plr.UserId].Mastery = {}
	end

	for _, Masteryy in ipairs(Mastery) do
		if temporalData[plr.UserId].Mastery[Masteryy] == nil or 0 then
			temporalData[plr.UserId].Mastery[Masteryy] = 1
		end
		local bool = Instance.new("NumberValue")
		bool.Name = Masteryy
		bool.Value = temporalData[plr.UserId].Mastery[Masteryy]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].Mastery[Masteryy] = bool.Value ---------- bug
end)
bool.Parent = AllMastery
end

AllMastery.Parent = plr

-------------------------------------------------------------------------------------
	
	local StoredFruit = Instance.new("Folder")
	StoredFruit.Name = "StoredFruits"

	temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

	if typeof(temporalData[plr.UserId].StoredFruits) ~= "table" then
		temporalData[plr.UserId].StoredFruits = {}
	end

	for _,  Fruit in ipairs(StoredFruits) do
		if temporalData[plr.UserId].StoredFruits[Fruit] == nil then
			temporalData[plr.UserId].StoredFruits[Fruit] = 0
		end
		local bool = Instance.new("StringValue")
		bool.Name = Fruit
		bool.Value = temporalData[plr.UserId].StoredFruits[Fruit]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].StoredFruits[Fruit] = bool.Value
		end)
		bool.Parent = StoredFruit
	end

	StoredFruit.Parent = plr

-------------------------------------------------------------------------------------
	
	local leader = Instance.new("Folder")
	leader.Name = "leaderstats"

	local Loadout = Instance.new("Folder")
	Loadout.Name = "Loadout"

	local Fruit = Instance.new("StringValue", Loadout)
	Fruit.Name = "Fruit"
	
	local FightingStyle = Instance.new("StringValue", Loadout)
	FightingStyle.Name = "FightingStyle"
	
	local Sword = Instance.new("StringValue", Loadout)
	Sword.Name = "Sword"
	
	local Race = Instance.new("StringValue", Loadout)
	Race.Name = "Race"
	
	local Title = Instance.new("StringValue", Loadout)
	Title.Name = "Title"
	
	local FruitLimit = Instance.new("NumberValue", Loadout)
	FruitLimit.Name = "FruitLimit"
	
-------------------------------------------------------------------------------------
	

	local Cash = Instance.new("NumberValue", leader)
	Cash.Name = "Cash"
	
	local Bounty = Instance.new("NumberValue", leader)
	Bounty.Name = "Bounty"

	leader.Parent = plr
	Loadout.Parent = plr

	Cash.Value = temporalData[plr.UserId].Cash or 0
	Cash:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Cash = Cash.Value
	end)

	Bounty.Value = temporalData[plr.UserId].Bounty or 0
	Bounty:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Bounty = Bounty.Value
	end)

	
-------------------------------------------------------------------------------------
	
	Fruit.Value = temporalData[plr.UserId].Fruit or "None"
	Fruit:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Fruit = Fruit.Value
	end)
	
	FightingStyle.Value = temporalData[plr.UserId].FightingStyle or "Basic"
	FightingStyle:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].FightingStyle = FightingStyle.Value
	end)
	
	Sword.Value = temporalData[plr.UserId].Sword or "None"
	Sword:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Sword = Sword.Value
	end)
	
	Race.Value = temporalData[plr.UserId].Race or "None"
	Race:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Race = Race.Value
	end)
	
	Title.Value = temporalData[plr.UserId].Title or "None"
	Title:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Title = Title.Title
	end)
	
	FruitLimit.Value = temporalData[plr.UserId].FruitLimit or 1
	FruitLimit:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].FruitLimit = FruitLimit.Value
	end)
	
-------------------------------------------------------------------------------------

	plr.AncestryChanged:Connect(function()
		if plr:IsDescendantOf(game) or typeof(temporalData[plr.UserId]) ~= "table" then
			return
		end
		if isStudio then
			print("Data not saved because it runs in Studio")
			return
		end
		local s, err = pcall(function()
			ds:UpdateAsync(plr.UserId, function()
				return temporalData[plr.UserId]
			end)
		end)
		if s ~= true then
			warn("Failed saving data for player: " .. plr.Name .. ", key: " .. plr.UserId .. "\n" .. tostring(err))
		else
			print("Data saved for player: " .. plr.Name)
		end
		temporalData[plr.UserId] = nil
	end)
end)

Now I could be completely wrong about this, but I think it’s because you keep rewriting
temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}
In each section.

This wipes everything you written to temporalData previously, including the mastery table. So when a value changes and looks for the mastery table within temporalData, it’s not there resulting in the error you’ve been getting.

I would only call the above line of code once and remove any other duplicate of it that’s below in the function.

Try this (I commented out the lines i think need to be removed):

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local isStudio = RunService:IsStudio()
local DataStoreService = game:GetService("DataStoreService")
local ds = DataStoreService:GetDataStore("LeaderStatSave")

local temporalData = {}

local FightingStyles = {
	"Ember Jujitsu",
	"Inferno Jujitsu",
	"Aquatic Fists",
	"Waterstream Fists",
	"Sliver Claws",
	"Midas Claws"
}
local Swords = {
	"Katana",
	"",
	"Samurai",
	"Leader",
	"Witch",
	"Divine"
}
local Mastery = {
	"Ember Jujitsu",
	"Inferno Jujitsu",
	"Aquatic Fists",
	"Waterstream Fists",
	"Katana",
	"Test",
	"Bomb",
	"Smoke",
	"Ice",
	"Chop",
	"Flame"
}
local StoredFruits = {
	"Bomb",
	"Smoke",
	"Ice",
	"Chop",
	"Flame"
}


Players.PlayerAdded:Connect(function(plr)
	local AllSwords = Instance.new("Folder")
	AllSwords.Name = "Swords"

	temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

	if typeof(temporalData[plr.UserId].Swords) ~= "table" then
		temporalData[plr.UserId].Swords = {}
	end

	for _, sword in ipairs(Swords) do
		if temporalData[plr.UserId].Swords[sword] == nil then
			temporalData[plr.UserId].Swords[sword] = false
		end
		local bool = Instance.new("BoolValue")
		bool.Name = sword
		bool.Value = temporalData[plr.UserId].Swords[sword]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].Swords[sword] = bool.Value
		end)
		bool.Parent = AllSwords
	end

	AllSwords.Parent = plr

	-------------------------------------------------------------------------------------

	local AllFightingStyles = Instance.new("Folder")
	AllFightingStyles.Name = "Fighting Styles"

	--temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {} -- remove this 

	if typeof(temporalData[plr.UserId].FightingStyles) ~= "table" then
		temporalData[plr.UserId].FightingStyles = {}
	end

	for _, FightStyle in ipairs(FightingStyles) do
		if temporalData[plr.UserId].FightingStyles[FightStyle] == nil then
			temporalData[plr.UserId].FightingStyles[FightStyle] = false
		end
		local bool = Instance.new("BoolValue")
		bool.Name = FightStyle
		bool.Value = temporalData[plr.UserId].FightingStyles[FightStyle]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].FightingStyles[FightStyle] = bool.Value
		end)
		bool.Parent = AllFightingStyles
	end

	AllFightingStyles.Parent = plr

	-------------------------------------------------------------------------------------

	local AllMastery = Instance.new("Folder")
	AllMastery.Name = "Masteries"

	--temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {} -- remove this

	if typeof(temporalData[plr.UserId].Mastery) ~= "table" then
		temporalData[plr.UserId].Mastery = {}
	end

	for _, Masteryy in ipairs(Mastery) do
		if temporalData[plr.UserId].Mastery[Masteryy] == nil or 0 then
			temporalData[plr.UserId].Mastery[Masteryy] = 1
		end
		local bool = Instance.new("NumberValue")
		bool.Name = Masteryy
		bool.Value = temporalData[plr.UserId].Mastery[Masteryy]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].Mastery[Masteryy] = bool.Value ---------- bug
		end)
		bool.Parent = AllMastery
	end

	AllMastery.Parent = plr

	-------------------------------------------------------------------------------------

	local StoredFruit = Instance.new("Folder")
	StoredFruit.Name = "StoredFruits"

	--temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {} remove this

	if typeof(temporalData[plr.UserId].StoredFruits) ~= "table" then
		temporalData[plr.UserId].StoredFruits = {}
	end

	for _,  Fruit in ipairs(StoredFruits) do
		if temporalData[plr.UserId].StoredFruits[Fruit] == nil then
			temporalData[plr.UserId].StoredFruits[Fruit] = 0
		end
		local bool = Instance.new("StringValue")
		bool.Name = Fruit
		bool.Value = temporalData[plr.UserId].StoredFruits[Fruit]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].StoredFruits[Fruit] = bool.Value
		end)
		bool.Parent = StoredFruit
	end

	StoredFruit.Parent = plr

	-------------------------------------------------------------------------------------

	local leader = Instance.new("Folder")
	leader.Name = "leaderstats"

	local Loadout = Instance.new("Folder")
	Loadout.Name = "Loadout"

	local Fruit = Instance.new("StringValue", Loadout)
	Fruit.Name = "Fruit"

	local FightingStyle = Instance.new("StringValue", Loadout)
	FightingStyle.Name = "FightingStyle"

	local Sword = Instance.new("StringValue", Loadout)
	Sword.Name = "Sword"

	local Race = Instance.new("StringValue", Loadout)
	Race.Name = "Race"

	local Title = Instance.new("StringValue", Loadout)
	Title.Name = "Title"

	local FruitLimit = Instance.new("NumberValue", Loadout)
	FruitLimit.Name = "FruitLimit"

	-------------------------------------------------------------------------------------


	local Cash = Instance.new("NumberValue", leader)
	Cash.Name = "Cash"

	local Bounty = Instance.new("NumberValue", leader)
	Bounty.Name = "Bounty"

	leader.Parent = plr
	Loadout.Parent = plr

	Cash.Value = temporalData[plr.UserId].Cash or 0
	Cash:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Cash = Cash.Value
	end)

	Bounty.Value = temporalData[plr.UserId].Bounty or 0
	Bounty:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Bounty = Bounty.Value
	end)


	-------------------------------------------------------------------------------------

	Fruit.Value = temporalData[plr.UserId].Fruit or "None"
	Fruit:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Fruit = Fruit.Value
	end)

	FightingStyle.Value = temporalData[plr.UserId].FightingStyle or "Basic"
	FightingStyle:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].FightingStyle = FightingStyle.Value
	end)

	Sword.Value = temporalData[plr.UserId].Sword or "None"
	Sword:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Sword = Sword.Value
	end)

	Race.Value = temporalData[plr.UserId].Race or "None"
	Race:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Race = Race.Value
	end)

	Title.Value = temporalData[plr.UserId].Title or "None"
	Title:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Title = Title.Title
	end)

	FruitLimit.Value = temporalData[plr.UserId].FruitLimit or 1
	FruitLimit:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].FruitLimit = FruitLimit.Value
	end)

	-------------------------------------------------------------------------------------

	plr.AncestryChanged:Connect(function()
		if plr:IsDescendantOf(game) or typeof(temporalData[plr.UserId]) ~= "table" then
			return
		end
		if isStudio then
			print("Data not saved because it runs in Studio")
			return
		end
		local s, err = pcall(function()
			ds:UpdateAsync(plr.UserId, function()
				return temporalData[plr.UserId]
			end)
		end)
		if s ~= true then
			warn("Failed saving data for player: " .. plr.Name .. ", key: " .. plr.UserId .. "\n" .. tostring(err))
		else
			print("Data saved for player: " .. plr.Name)
		end
		temporalData[plr.UserId] = nil
	end)
end)

If this doesn’t work, or taking those lines out actually breaks it more, let me know and I can look it over again.