"attempt to index nil with 'Value' " Error When I Try To Get Value From Remote Event Table

I’m trying to pass a table from my script to a localscript, and it’s partially working. The problem is, I have values in the table that are assigned to be equal to numValues that are placed in ServerStorage. When I want to print out the “.Value” of the numbers (from the table) in the localscript (after receiving the remote event) it gives me the error, "attempt to index nil with ‘Value’ ".

EDIT: Quick note. When I click the button, it prints out “1 nil”, which is the first .Name, then gives me that error.

So the main thing I’m trying to accomplish is the following. To have the script that has the table pass that table to the client, then have the client loop through the table and print out every one of the “Name” and “Time.Value” in that table.

I’m speculating that it’s because the values that are in the table are assigned to be equal to numbers in ServerStorage. Thus, when I try to do “.Value” on them from the localscript, it can’t find the values due to them being in ServerStorage. Interestingly enough, when I go to the table (in the server script) and change the numbers from “Time = Time1” to “Time = Time1.Value”, now it works! But I can’t do that, due to me using .Changed in the system I’m creating. Any ideas? Here’s sections of the code:

Script (Placed In ServerScriptService):

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")

-- Variables
local GuiEvent = ReplicatedStorage:WaitForChild("RaceStats")

local Time1 = ServerStorage.PlayerTimes.Time1
local Time2 = ServerStorage.PlayerTimes.Time2
local Time3 = ServerStorage.PlayerTimes.Time3
local Time4 = ServerStorage.PlayerTimes.Time4

-- Creates Main Table
local PlayerAssignments = {
	{Name = "1nil", Time = Time1, Bool = RacingBool1},
	{Name = "2nil", Time = Time2, Bool = RacingBool2},
	{Name = "3nil", Time = Time3, Bool = RacingBool3},
	{Name = "4nil", Time = Time4, Bool = RacingBool4}
}

GuiEvent.OnServerEvent:Connect(function()
	GuiEvent:FireAllClients(PlayerAssignments)
end)

LocalScript (Placed In Gui Under Button):

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Variables
local button = script.Parent
local StatsRemote = ReplicatedStorage:WaitForChild("RaceStats")

button.MouseButton1Click:Connect(function()
	StatsRemote:FireServer()
end)

StatsRemote.OnClientEvent:Connect(function(PlayerAssignments)
	for Var, Players in pairs(PlayerAssignments) do
		print(Players.Name)
		print(Players.Time.Value)
	end
end)

Thanks for any help!

2 Likes

Hi! Try encoding the table (using http service) and then passing it through, though it might fail encoding the Time1, Time2, etc since it seems those are objects and not tables. Maybe replace those with the actual times? (a number) and then try encoding them… If you insist passing the raw table, then those variables are most likely the issue, since the client cannot access the Server Storage, only the server can. Also, the reason i suggest encoding the table it’s because it’s faster than just passing it as a regular table here is a speed test i did:
SpeedDiff
And my implementation of the speed test, hierarchy:
hierarchy
SendTable:
sendTable
Receive:
Recieve
SendOtheSecretr:
SendOtherSecret

2 Likes

Oh interesting. I’ve never looked into what httpservice does really. I always thought that it was for things like using external databases. I’m not understanding what you said does exactly. I’ll see what I can find about httpservice, though is there anywhere you could point me to that talks about the method you’re using, so that I could understand it better? Thanks for the response

Yes of course, apologies for not explaining the method used. Basically, JSONEncode converts a table to a JSON string, and JSONDecode converts a json string to a table, httpservice is normaly used to make requests to 3rd party APIs, which can do any number of things from storing data to a database, getting data, or really anything you can do using REST APIs. To iterate what i said earlier, passing a string (the table converted to a JSON string) is a tad bit faster than just passing the table on its own through the remote event/function.

Hopefully i clarified a bit. Here’s Roblox documentation on httpservice: HttpService | Documentation - Roblox Creator Hub

Ohhh I see. So it’s like compressing and uncompressing it through the JSON format?

Thanks for the help with that. I’ll look into implementing that when I get a chance. When it comes to the values being a “server only” numValue (so to speak), is there a way I could get the value of them when passing it to the client? The only thing I can think of doing is making another entry in the table, that is instead of:

local PlayerAssignments = {
	{Name = "1nil", Time = Time1, Bool = RacingBool1},
	{Name = "2nil", Time = Time2, Bool = RacingBool2},
	{Name = "3nil", Time = Time3, Bool = RacingBool3},
	{Name = "4nil", Time = Time4, Bool = RacingBool4}
}

Making it:

local PlayerAssignments = {
	{Name = "1nil", Time = Time1, TimeValue1 = Time1.Value, Bool = RacingBool1},
	{Name = "2nil", Time = Time2, TimeValue2 = Time2.Value, Bool = RacingBool2},
	{Name = "3nil", Time = Time3, TimeValue3 = Time3.Value, Bool = RacingBool3},
	{Name = "4nil", Time = Time4, TimeValue4 = Time4.Value, Bool = RacingBool4}
}

Adding the “TimeValue” into the table. I just don’t want things to get too messy. The reason I can’t do Time1.Value, Time2.Value, etc. only, is because I’m later doing this:

Players.Time.Changed:Connect(function()
				print(Players.Name .. " " .. Players.Time.Value)
			end)

And the “.Changed” doesn’t work on the .Value of it, only on the Time itself. Would there be a way to find the “Parent” or something of the .Value? I’ll probably just end up adding that extra chunk into the table otherwise.

Thanks.

1 Like

Odd. I just tried making a variable in the table named “TimeValue”, that’s the “Time.Value”. What’s strange is that it continually shows 0 when printed.

What I’m trying to do is have 4 values (one for each player), and make them count up by 0.1 seconds. Right now I’ve been doing it with 4 scripts running at the same time, one for each value. Then I take those values, and put them in a table (the one I showed earlier) along with the player’s names.

I want to be able to show these values, along with the player names on a gui, thus why I’m trying to use a remote event to send the table to a localscript. Perhaps you have some knowledge on why the “TimeValue” is showing 0 when I print it, even though using “Time.Value” in the rest of my script works. Here’s those sections of what I’ve been trying:

Main Script:

-- Variables
local GuiEvent = ReplicatedStorage:WaitForChild("RaceStats")

local Time1 = ServerStorage.PlayerTimes.Time1
local Time2 = ServerStorage.PlayerTimes.Time2
local Time3 = ServerStorage.PlayerTimes.Time3
local Time4 = ServerStorage.PlayerTimes.Time4

-- Creates Main Table
local PlayerAssignments = {
{Name = "1nil", Time = Time1, TimeValue = Time1.Value, Bool = RacingBool1},
{Name = "2nil", Time = Time2, TimeValue = Time2.Value, Bool = RacingBool2},
{Name = "3nil", Time = Time3, TimeValue = Time3.Value, Bool = RacingBool3},
{Name = "4nil", Time = Time4, TimeValue = Time4.Value, Bool = RacingBool4}
}

	for Var, Players in pairs(PlayerAssignments) do -- Cycles through the table
		if Players.Name == "1nil" then
			Players.Name = Player.Name -- Makes the name in the table equal to what the player name is
			Players.Time.Changed:Connect(function()
				print(Players.Name .. " " .. Players.TimeValue)
			end)
			break -- Stops the loop
			-- Continues on doing the same thing, checking each name value in the table
		elseif
			Players.Name == "2nil" then
			Players.Name = Player.Name
			Players.Time.Changed:Connect(function()
				local TimeValue2 = Time2.Value
				print(Players.Name .. " " .. Players.TimeValue)
			end)
			break
		elseif
			Players.Name == "3nil" then
			Players.Name = Player.Name
			Players.Time.Changed:Connect(function()
				local TimeValue3 = Time3.Value
				print(Players.Name .. " " .. Players.TimeValue)
			end)
			break
		elseif
			Players.Name == "4nil" then
			Players.Name = Player.Name
			Players.Time.Changed:Connect(function()
				local TimeValue4 = Time4.Value
				print(Players.Name .. " " .. Players.TimeValue)
			end)
			break
		end
	end

-- Receives RemoteEvent From GUI LocalScript, Then Fires Back To All Clients
GuiEvent.OnServerEvent:Connect(function()
	GuiEvent:FireAllClients(PlayerAssignments)
end)

LocalScript:

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Variables
local button = script.Parent
local StatsRemote = ReplicatedStorage:WaitForChild("RaceStats")

button.MouseButton1Click:Connect(function()
	StatsRemote:FireServer()
end)

StatsRemote.OnClientEvent:Connect(function(PlayerAssignments)
	for Var, Players in pairs(PlayerAssignments) do
		print(Players.Name)
		print(Players.TimeValue)
	end
end)

One Of The Four (Near Identical) Scripts That Change The Four Values:

-- Variables
local RacingBool1 = game.ServerStorage.RacingBools.RacingBool1
local RacingBool2 = game.ServerStorage.RacingBools.RacingBool2
local RacingBool3 = game.ServerStorage.RacingBools.RacingBool3
local RacingBool4 = game.ServerStorage.RacingBools.RacingBool4

local RaceTime1 = game.ServerStorage.PlayerTimes.Time1
local RaceTime2 = game.ServerStorage.PlayerTimes.Time2
local RaceTime3 = game.ServerStorage.PlayerTimes.Time3
local RaceTime4 = game.ServerStorage.PlayerTimes.Time4

wait(5)

while RacingBool1.Value == false do
	if RacingBool1.Value == false then
	RaceTime1.Value = RaceTime1.Value + 0.1
	wait(0.1)
	end
end

Sorry if this is a lot to try to look through. Simply put, the problem is in the first Script at the top. The “TimeValue” variable in the table doesn’t change from 0. Any ideas? Thanks!

The issue why the value objects are nil is because sending instances over remote does not work the way you think it does. When you send an instance over a remote event it passes a reference to the actual object, the value is nil because the client cannot see anything contained in server storage. So what you will have to do is place those value objects into a location that the client can also access, for example Replicated Storage.

1 Like

Have you checked if it is getting past the is statement in the while loop? if not try putting a print statement inside it and check if its printing

This isn’t printing “nil”, it’s printing “0”. And what I’m doing isn’t through a remote event right now. I’m still testing it from within the server script. Thanks for the info though.

I thought you wanted to send it to the client, why are sending it over the server again?

I’m sure that everything is working. It does print it every 0.1 seconds when the value changes, but it’s just stuck at 0. When I go into the server script and replace

Players.Time.Changed:Connect(function()
				print(Players.Name .. " " .. Players.TimeValue)
			end)

with

Players.Time.Changed:Connect(function()
				print(Players.Name .. " " .. Players.Time.Value)
			end)

it works!

I’m very confused as to why this is happening/

1 Like

Yes because its going to store the original value in the table, it not going to automatically update you need to do that yourself.

I’m not. I’m saying that right now, I’m not using any remote events when I’m printing out the value in the server script. The other remoteevent is for when I click a button - I’m not testing that yet. The problem is this part in the Script:

for Var, Players in pairs(PlayerAssignments) do -- Cycles through the table
		if Players.Name == "1nil" then
			Players.Name = Player.Name -- Makes the name in the table equal to what the player name is
			Players.Time.Changed:Connect(function()
				print(Players.Name .. " " .. Players.TimeValue)
			end)
			break -- Stops the loop

The “print(Players.Name … " " … Players.TimeValue)” part is what’s strange. When I replace “Players.TimeValue” with “Players.Time.Value” it works! But when I say “Players.TimeValue” which I declared at the beginning of the script and placed in the table, it still prints the Name and the Value, but it’s just stuck at 0!

i think this is because when u first set the table, the Players.TimeValue is equal to 0. When you print the
Players.Time.Value it gives you the up-to-date value of the Value rather than the value which was set when the dictionary was created.

1 Like

Yeah, I was thinking something similar. I’m just confused as to why this is happening when I did a .Changed for the Time.Value. I’ll try doing “TimeValue.Changed” instead.

EDIT: I forgot. I can’t do “TimeValue.Changed” because .Changed only works on the Value object itself, not the .Value.

Sadly you cannot use the Changed event on a Number, this will throw an error. I would say just update the dictionary when the while loop changes it OR use the Time.Value instead to get the up-to-date value.

1 Like

Oh haha. I just edited in the same thing.

Any ideas on how to fix the problem with it being stuck at 0? I’ll play around with it myself in the meanwhile.

I would simply use the .Changed event on Time OR update the dictionary when changing the value of Time in the while loop.

1 Like