Argument 1 Missing or Nil

Evening, I’m having trouble with this script i’m making:

DSS = game:GetService("DataStoreService")
HTTPS = game:GetService("HttpService")

local CharStats = DSS:GetDataStore("MainCharacterStats")

PlrStats = {
	['Currency'] = 0,
	['CoreShape'] = "None",
	['CoreType'] = "None"
}


game.Players.PlayerAdded:Connect(function(Joinedplr)
	
	--local success, errorMessage = pcall(function()
	local ObtainedData = CharStats:GetAsync(Joinedplr.UserId)
	if ObtainedData then
		local ObtainedData = HTTPS:JSONDecode(ObtainedData)
		print(tostring(ObtainedData['Currency']))
	else print("No Data.")
		
	end
	end)
	
	--[[if errorMessage then
		print("Error occured whilst Saving")
		warn(errorMessage)
	end
end)]]

game.Players.PlayerRemoving:Connect(function(Leftplr)
	local success, errorMessage = pcall(function()
		CharStats:SetAsync(Leftplr.UserId.."BasicStats",HTTPS:JSONEncode(PlrStats))
		print("Data saved Successfully.")
	end)

	if errorMessage then
		print("Error occured whilst Saving")
		warn(errorMessage)
	end
end)

I’m trying to turn a dictionary into a JSON format so it can be stored into a Datastore but i’m getting the title error whenever asking the script to Decode the data.

Any help is appreciated, i’m very new to datastores so i’m not 100% sure of what im doing is efficent or if there is a better way of going around it.
the three questions above, you should probably pick a different category.

the PCall being in comments is intentional, I wanted to see what specific line was throwing errors.

it was this line:

local ObtainedData = HTTPS:JSONDecode(ObtainedData)

so I added

	else print("No Data.")

now this always prints even if

print("Data saved Successfully.")

is printed.

I wonder why you encoding it to json, because never heard you have to

Roblox converts tables to strings for you, not sure if this is necessary. You can just store the table.

you can’t set a variable to itself,

local ObtainedData = HTTPS:JSONDecode(ObtainedData)

You’re saying that ObtainedData is itself decoded.

Apparently Datastores can’t store Dictionaries or Tables, so people usually encode it into JSON which datastores can keep. and then decode it back when the data is called back.

I believe it was mentioned here

1 Like

I did try making it a different variable but this threw the same error

You may have heard that you’d need to run HttpService:JSONEncode() on it to turn the table into a string but IIRC it is completely unnecessary as Roblox turns the table into a string with or without the JSONEncode function. Summed up it’s just repeating a function that Roblox is already running and a general waste of time.

tl;dr yes you can use :SetAsync() without doing anything to the table

Quoting someone else but yes datastores can save tables.

2 Likes

Yes but you see why that makes no sense right? Obtained data should be getasync

You wouldn’t put local infront of it anymore either as it’s been declared already, I think yo ucan fix your entire issue by removing local infront of ObtainedData (the second one)

But still, I’m freely saving tables inside datastore because roblox does thing for you
I dont do anything to a table

1 Like
game.Players.PlayerAdded:Connect(function(Joinedplr)
	
	--local success, errorMessage = pcall(function()
	local ObtainedData = CharStats:GetAsync(Joinedplr.UserId) -- FIRST LOCAL
	if ObtainedData then
		local ObtainedData = HTTPS:JSONDecode(ObtainedData) -- ALREADY SET AS LOCAL ABOVE
		print(tostring(ObtainedData['Currency']))
	else print("No Data.")
		
	end
	end)
	
	if errorMessage then
		print("Error occured whilst Saving")
		warn(errorMessage)
	end
end

So just remove the local or rename it:

game.Players.PlayerAdded:Connect(function(Joinedplr)
	
	--local success, errorMessage = pcall(function()
	local ObtainedData = CharStats:GetAsync(Joinedplr.UserId)
	if ObtainedData then
		ObtainedData = HTTPS:JSONDecode(ObtainedData) -- LOCAL GONE/RENAMED (local decoded = HTTPS:JSONDecode(ObtainedData)
		print(tostring(ObtainedData['Currency']))
	else print("No Data.")
		
	end
	end)
	
	--[[if errorMessage then
		print("Error occured whilst Saving")
		warn(errorMessage)
	end
end

Or just don’t encode/decode it in the first place

1 Like

yeah I removed the JSON encode thingy, I thought you had to do that since multiple articles said so, must’ve been updated at some point i suppose but i don’t really know, nice to hear i dont need to do that though, thanks!

doing as you’ve said, i’m not getting the error anymore but data still isn’t being retrieved (“no data”) is still being printed only

removing the else statement doesn’t show an error either

1 Like

wrap it in a pcall and print the error, I use modules usually so I don’t run into data issues much, try the pcall thing and send the output and FULL code please.

PCall also isn’t returning anything, The code sent in the original post is the full code but if you mean what I have now then:

DSS = game:GetService("DataStoreService")
HTTPS = game:GetService("HttpService")

local CharStats = DSS:GetDataStore("MainCharacterStats")

PlrStats = {
	['Currency'] = 0,
	['CoreShape'] = "None",
	['CoreType'] = "None"
}


game.Players.PlayerAdded:Connect(function(Joinedplr)
	
	local success, errorMessage = pcall(function()
	local ObtainedData = CharStats:GetAsync(Joinedplr.UserId)
	if ObtainedData then
		print(tostring(ObtainedData['Currency']))
	end
	end)
	
	if errorMessage then
			print("Error occured whilst Saving")
			warn(errorMessage)
		end
	end)

game.Players.PlayerRemoving:Connect(function(Leftplr)
	local success, errorMessage = pcall(function()
		CharStats:SetAsync(Leftplr.UserId.."BasicStats",PlrStats)
		print("Data saved Successfully.")
	end)

	if errorMessage then
		print("Error occured whilst Saving")
		warn(errorMessage)
	end
end)

You’re not returning on the data stores

like this:

local success, data = pcall(function()
	return CharStats:GetAsync(Joinedplr.UserId)
end)

I see, I haven’t actually used return before so I didn’t know, thanks!

I’ve noticed that print statements don’t work when being placed after a return, so I can’t check if saving was successful

So, I quickly made a small clickdetector that gives me 500 on the currency value every time its clicked. I did confirm that this was working as it prints teh added values in the output:
image

Despite this however, re-entering the game sets the currency value back to 0, so it was never saved.

this is the code now:

DSS = game:GetService("DataStoreService")
HTTPS = game:GetService("HttpService")

local CharStats = DSS:GetDataStore("MainCharacterStats")

PlrStats = {
	['Currency'] = 0,
	['CoreShape'] = "None",
	['CoreType'] = "None"
}


game.Players.PlayerAdded:Connect(function(Joinedplr)
	
	local success, CharStats = pcall(function()
		return CharStats:SetAsync(Joinedplr.UserId.."BasicStats",PlrStats)
	end)
end)

game.Players.PlayerRemoving:Connect(function(Leftplr)
	local success, CharStats = pcall(function()
		return CharStats:SetAsync(Leftplr.UserId.."BasicStats",PlrStats)
	end)
end)

script.ManageMoney.Event:Connect(function(FiredPlr, amount)
	CharStats:UpdateAsync(FiredPlr.UserId.."BasicStats",function(oldvalue)
		print(tostring(oldvalue['Currency']))
		local Array = oldvalue
		Array['Currency'] = Array['Currency'] + amount
		return Array
	end)
end)

return always end a function, so you want to put it at the end, alternatively it can be used to exit out of a function early:

local isCool = false

local function areYouCool()
     if not isCool then return end
     print("He's cool")
end

In this case it will never get printed because the condition wasn’t met
Back to your data stores though

“I’ve noticed that print statements don’t work when being placed after a return, so I can’t check if saving was successful”

You can, just print success.

Despite this however, re-entering the game sets the currency value back to 0, so it was never saved.

You’re setting data even before checking if said player has any data, you wanna do GetAsync and THEN if the player has no data (it will return nil), will you want to set the players data.
In other words when a players join you’ll first do getasync, if it returns data boom you have your data, if it doesn’t, then give the player base data by doing setasync (Like setting their coins to 0 etc.)
Data is complicated and a lot can go wrong, I recommend using a module if you’re no proficient enough to make your own, people can easily lose data if the server crashes and so on.

That post is mentioning that you can’t store Roblox specific types in Datastores, like Enums or BrickColors, and that tables are fine.

1 Like