How can I avoid "is not a valid member of ...." error without wrapping the code in a ton of if statements?

I had always thought that leading up to this point, using ‘or’ like so:

local value = workspace.Part or nil

would return nil if workspace.Part did not exist, however, I’ve been getting errors recently, most recently with this snippet.

function Controller:SwingEffect()
	print(self)
	local RTrail = self.CharacterObject["Right Arm"].Effect or nil
	local LTrail = self.CharacterObject["Left Arm"].Effect or nil
	local FTrail = self.CharacterObject["Right Leg"].Effect or nil
	
	if RTrail == nil or LTrail == nil or FTrail == nil then warn("One or more trails do not exist") 
           return end
        end

I just get this error:

Effect is not a valid member of Part “Workspace.Sekuriyo.Right Arm” - Client - Controller:50

I really don’t want to wrap my code in a ton of if statements to check if this == this and was looking for a more compressed solution to this issue.

Hmm. To me honestly that sound pretty useless.

If there is no workspace.Part you don’t need to put or nil because it will be nil if you index it to something that doesn’t exist…

The only reason why I would use is if I want to distinguish between false and nil

Anyways if you want to check something you NEED to have an if statement. There is no other way except Boolean operations however if you want your code to not have stacked if statements there are ways you can get around it by using not or by using loops. In your case not operator would be better.

function Controller:SwingEffect()
	print(self)
	local RTrail = self.CharacterObject["Right Arm"]:FindFirstChild("Effect")
	local LTrail = self.CharacterObject["Left Arm"]:FindFirstChild("Effect")
	local FTrail = self.CharacterObject["Right Leg"]:FindFirstChild("Effect")

	
	if not (FTrail and RTrail and LTrail) then
       return end
    end
    -- Rest of code goes here
end)

You can see that the not operator simply negates the outcome.

4 Likes

without if statements? no problem

function Controller:SwingEffect()
	print(self)
    local err, message = pcall(function()
    local RTrail = self.CharacterObject["Right Arm"].Effect
	local LTrail = self.CharacterObject["Left Arm"].Effect
	local FTrail = self.CharacterObject["Right Leg"].Effect
    -- continue your code
    end)
    if msg then warn(msg) end -- incase you want to read the errors again
 end

The point is that it errors if workspace.Part doesn’t exist, it doesn’t get to the point of returning nil since it just breaks the code before that point. the pcall suggested by @asgm is what I was looking for.

This is inefficient and code smell—not a valid solution to the problem. Please do not do use pcall when there is a function specifically made for this purpose. FindFirstChild is the correct way to check if a child exists, not writing broken code and checking if it throws an error. I recommend reading this useful article which lists usecases for what pcall is supposed to be for:

In short, pcall should be used for stuff that you cannot help erroring. For example, Datastore’s GetAsync calls can error if there’s network issues, and there’s nothing a developer can do to stop it other than detecting when it happens.

It can also be used for debugging, but the Error event is preferable in most cases with that purpose. Regardless, it should not be used in production code for entirely user-made functions that do not make unsafe calls.

6 Likes

Definitely don’t use pcall. That’s a really bad idea. Use FindFirstChild and it won’t error.
self.CharacterObject[“Right Arm”]:FindFirstChild(“Effect”)
Never use pcall for errors that are within your power to fix.

4 Likes

I highly do not recommend using pcall. pcall is usually for things that are prone to fail like networks. I highly recommend using an if statement

2 Likes