If value == nil not working

I am making a tycoon game and in my script, I implemented this if statement

if Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID ~= Button.Name then

The output said: 19:15:06.753 Workspace.Tycoons.Plots.Template.Objects.Buttons.Button Executor:20: attempt to index nil with 'ID' - Server - Button Executor:20
The script returned that the value was nil (I believe so), so I tried another way to execute this code:

if Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID == nil or Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID ~= Button.Name then

This is nerve-racking, I wrote that if the script returns nil, then the piece of line underneath it will execute, but instead it gave me again the same error output, when I literally just said that the code will continue if it returns nil! I’ve been working on this issue for hours and I couldn’t find a single solution. Even my friend of mine was experiencing the same issue! Please, if anyone in this community knows the answer, I’d love you to tell me :pleading_face:. Many thanks for considering my request.

Note: Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID is a table, not an instance

2 Likes

You are not allowed to instance non existent Instances in Luau. The provided approach only works for tables and not for Instances. You can use :FindFirstChild() instead to get a nil value if a child with the provided name does not exist.

1 Like

Sadly, this is a table, I will edit my post

What happened when you tried the other way to execute the code?

1 Like

If you don’t mind my asking…

What was the error? Was it the same as the previous one?

1 Like

It was the same error, I am very sorry for not including this message

Try changing

Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID == nil or Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID ~= Button.Name then

to

Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name] == nil or Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID == nil or Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID ~= Button.Name then
4 Likes

try this:

if
	Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name] and
	Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name].ID
then
	print("found button")
end

The issue is not that .ID is nil, the issue lies with Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name]. Taking a closer look at the error message Luau is saying that you’re attempting to index the datatype nil with .ID.

5 Likes

For the love of god, please use variables if you’re going to make long-index paths like these

2 Likes

NO WAY, THANK YOU SO MUCH @randomlletters!

I am master of organization, here is how I organize things:

Currencies = {
		Cash = 0,
		Gems = 0
	},
	Tycoon = {
		Floors = {
			["1"] = {
				Buttons = {}
			}
		},
		Settings = {
			Colorizing = {
				DropColor = {Red = 0, Green = 0, Blue = 0},
				WallColor = {Red = 0, Green = 0, Blue = 0}
			}
		}
	},
	Session = {
		LogInDates = {},
		TimeSpent = 0
	}
}

I love making so many useless tables

Nobody has explained why that solution works. Do you understand why, or would you like me to elaborate?

I didn’t really understand, I am eager to hear your explanation If you want. Thanks a lot!

About the error

To index something is to use the dot operator. An index operation allows you to read keys of tables and members (properties/children/functions) of instances. The error “attempt to index nil with x” is commonly mistaken as “x” being a non-existent key of the indexed table or member of the indexed instance; however, it is not “x” which is non-existent, but what precedes it that is. This means that the following code results in that error:

nil.x

It holds up that we’re using the dot operator on nil, which is described by “attempt to index nil”.

Why

Your error states that you indexed nil with “ID”, so the task that befalls you now is to locate where in your code do you proceed the dot operator with “ID”. That is with the following piece of code:

Buttons[Button.Name].ID

This suggests that the preceding code is resulting in nil:

Buttons[Button.Name]

The above code is, in it of itself, another index operation. You’re attempting to find a key in the dictionary Data.Tycoon.Floors[Floor.Name].Buttons that matches the name of the given button. No key by that button’s name could be found, however, so nil became of that index operation. This means one of two things:

  1. Where a button was expected, it was not found. This is a problem in its own right and requires further investigation.

  2. Out of the buttons traversed, only some are supposed to yield results. If this is the case, your code needs to account for the buttons that do not belong.

What to do

@randomlletters and @DataSigh both provided solutions geared towards scenario #2. To summarize, they’re ensuring that the index operation Buttons[Button.Name] yields a result before attempting to interact with it. Putting that into a more intuitive form helps shed some light:

local button = Data.Tycoon.Floors[Floor.Name].Buttons[Button.Name]
if button then
    -- A button exists, now we can read its ID
end

How exactly they compress this assertion into a one-line conditional is reliant on the behaviour of logical operators

1 Like

Oh wow, I did expect such a lengthy response! Thank you for your patience!