:GetAttribute() from string when requested variable is an instance

I’m having trouble getting attributes using :GetAttribute().

Basically, the localscript gets the configuration instance (which is correct, I have checked to see if it was an instance) in ReplicatedStorage, and sends it off to the serverscript where attributes are added and returned. This is then passed on to the InsideParty() function.

InsideParty() tries to grab the “Owner” attribute from the configuration, but the error ‘attempt to call missing method 'GetAttribute' of string’ is raised.

The confusing part about this is that it sends through an instance and comes back with a string. Why does it do this?

Here are the scripts:
PlayerScript (local), displayParties() function:

function displayParties()
	if gui.MatchmakingFrame.Visible == true then
		if #rs.MultiplayerMatches:GetChildren() > 0 then
			for _, box in pairs(gui.MatchmakingFrame.ScrollingFrame:GetChildren()) do
				if box:IsA("Frame") and box.Visible == true then
					box:Destroy()
				end
			end
			for _, match in pairs(rs.MultiplayerMatches:GetChildren()) do
				local box = gui.MatchmakingFrame.ScrollingFrame.Default:Clone()
				box.Name = match.Name
				box.PartyName.Text = match:GetAttribute("PartyName")
				box.Members.Text = match:GetAttribute("Members").."/"..match:GetAttribute("MaxMembers")
				box.Type.Text = match:GetAttribute("Type")
				box.Owner.Text = match:GetAttribute("Owner")
				match:GetAttributeChangedSignal("Members"):Connect(function()
					box.Members.Text = match:GetAttribute("Members").."/"..match:GetAttribute("MaxMembers")
				end)
				match:GetPropertyChangedSignal("Parent"):Connect(function()
					if not match.Parent then
						box:Destroy()
					end
				end)
				box.Join.MouseButton1Click:Connect(function()
					if match:GetAttribute("Members") < match:GetAttribute("MaxMembers") then
						if match:GetAttribute("Status") ~= "Starting" then
							local result = remoteFunction:InvokeServer("JoinMatch", match)
							if result then
								InsideParty(result)
							end
						else
							Msg("This match has already started.", 4, Color3.new(0.9, 0, 0))
						end
					else
						Msg("This party is full.", 3, Color3.new(0.75, 0, 0))
					end
				end) 
				box.Parent = gui.MatchmakingFrame.ScrollingFrame
				box.Visible = true
			end
		end
	end
end

ServerScript, responding to the remote function:

elseif action == "JoinMatch" then
		local hasBall = false
		for i = 1, 5 do
			if game.ServerStorage.Spheres:FindFirstChild(player:GetAttribute("Sphere"..i)) then
				hasBall = true
				break 
			end
		end
		if hasBall == false then player:Kick("") end
		local match = val
		if not match then return false end
		if match:GetAttribute("Members") >= match:GetAttribute("MaxMembers") then
			return "Full"
		elseif match:GetAttribute("Status") == "Starting" then
			return "Started"
		else
			for _, party in pairs(rs.MultiplayerMatches:GetChildren()) do
				if party:FindFirstChild(player.Name) then
					return "InMatch"
				end
			end
			match:SetAttribute("Members", #match:GetChildren())
			local p = Instance.new("Folder", match)
			p.Name = player.Name
			p:SetAttribute("Order", #match:GetChildren())
			local done = nil
			local image = nil
			repeat
				local success, error = pcall(function()
					local img, success, loaded = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
					if success and loaded then
						image = img
						return
					end
				end)	
			until done and image
			p:SetAttribute("Image", image) 
			return match
		end

I will note that it is almost 12am as I am writing this, so I will not respond for a while.

1 Like

It’s cause you’re returning a string

local result = remoteFunction:InvokeServer("JoinMatch", match)
	if result then
		InsideParty(result)
	end

text

if match:GetAttribute("Members") >= match:GetAttribute("MaxMembers") then
	return "Full"  ------------------------------- Returning String here
elseif match:GetAttribute("Status") == "Starting" then
	return "Started"  ------------------------------- Returning String here
else
	for _, party in pairs(rs.MultiplayerMatches:GetChildren()) do
		if party:FindFirstChild(player.Name) then
			return "InMatch" ----------------------- Returning String here
		end
	end

And if my assumption is correct, this is what you want returned

until done and image
p:SetAttribute("Image", image) 
return match -- Thing you probably want

When you call this function
local result = remoteFunction:InvokeServer("JoinMatch", match)
It returns one of these results
return "Full"
return "Started"
return "InMatch"
so result = one of the strings above.
And when it runs if result then it’s checking if the result is real, or not nil
And since a string is not nil it continues to run
And since you’re trying to call :GetAttribute() on string, it fails, as, well, you can’t

To fix you can:

  1. Replace return with continue
  2. Remove the return code and the code doing the return altogether as it doesn’t seem like you need it

Thank you! I’ve done some more digging, and have realised this is the cause of another issue.

In ServerScript, there is a repeat statement trying to get the thumbnail of the player. This fails, but the player’s folder is created. When pressing the join button again, the attempt to call missing method 'GetAttribute' of string error is raised as it finds the player in a match.

To correctly function, the InsideParty() function needs the player’s thumbnail, but why does it fail? The repeat loop doesn’t grab the image, and there’s no apparent reason why.

If you can, further help would be appreciated.

I’m assuming you’re having problems with this code

local done = nil
local image = nil
repeat
	local success, error = pcall(function()
		local img, success, loaded = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
		if success and loaded then
			image = img
			return
		end
	end)	
until done and image

Well,

  1. You don’t need the done = nil or image = nil variable or the repeat until loop, in short, delete all the code from above .-.
  2. Looking at the documentation for Players:GetUserThumbnailAsync(), it seems you don’t need a pcall function as Players:GetUserThumbnailAsync() is kinda like a pcall. It also doesn’t return 3 values, only 2. Example code on how to use GetUserThumbnailAsync() below
local returnVal, didRun = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
-- returnVal is your image, you can change returnVal back to image if you want
-- didRun checks if it returned a valid image or not (I think), it'll either be true or false, true if it's actually a valid image, false if it wasn't, you can change this back to success if you want
  1. After that all you need to do is, add an if then statement to check whether or not picture is a valid or not and continue on with your code
local returnVal, didRun = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
if didRun == true then
	-- create folder with attribute and all that
else
	-- if, for some reason it wasn't a picture then maybe make this into a loop? idk I'm fairly certain it should be a 100% chance for no error, if the values are all placed correctly.
end

yapping session that doesn't really relate to topic but you should probably know

Somethings to note that I forgot to mention on my first post, you don’t need to use ipairs or pairs anymore you can just use the table how it is, in short

-- While yes the below code still works, there's a simpler way of doing it
for _, party in pairs(rs.MultiplayerMatches:GetChildren()) do
	
end
-- You can replace above code with below code, and it'll still work as intended
for _, party in rs.MultiplayerMatches:GetChildren() do
	
end
-- replaceable for both ipairs() and pairs()

Why should you replace the code?
Well ipairs and pairs work differently depending on which type of table you have, rather spending time remembering them, you can just do it the new way :sunglasses: Though there will probably be a time when you will need to use ipairs or pairs, just 99% of the time you can just use the new way.

separator :d

The below code seems like a really inefficient way of, I think, finding which player has the ball.

local hasBall = false
for i = 1, 5 do
	if game.ServerStorage.Spheres:FindFirstChild(player:GetAttribute("Sphere"..i)) then
		hasBall = true
		break 
	end
end

I’d give more details but, you could be doing it this way for a specific reason that I don’t know of, and I don’t have the game, so it’s really not my problem. Just saying there’s probably an easier doing it.

separator 2

You were using pcall wrong [EDIT: You were using it right, it’s just that 2 variables have the same name, which confused me. Don’t give variables the same names. That just makes everything harder for everyone.]

local success, error = pcall(function()
	local img, success, loaded = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
	if success and loaded then
		image = img
		return
	end
end)

The if success then should be out of the pcall like this

local success, error = pcall(function()
	local returnVal, didRun = game.Players:GetUserThumbnailAsync(player.UserId, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size352x352)
end)
if success then
	-- do stuff
end

Also for better naming convention I would call a pcall like this

local didRun, returnVal = pcall(function()
	return "Ran"
end)

just like the GetplayerimageAsyc or whatever it was called, didRun checks if it ran. If it did would be true with returnVal being “Ran”

It didRun was false, that means there was an error, and the error would be stated in the returnVal

Egg :egg:

[Stuff from below are EDITS]
Normally I don’t ask this but, how good are you at coding? When I see bacon hairs on the Forums I usually assume it’s a knowledgeable coder that’s on an alt account. But you don’t really seem that good at coding. Which is fine. I’m just asking how good you are so I can reduce the amount of yapping I have to do with each Post I make

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.