When I Join the game it keeps say this error
ServerScriptService.DataStorage.RankCreator:36: invalid argument #3 (string expected, got nil):
The error is occuring at line 36
local DataStoreService = game:GetService("DataStoreService") local dataStore = DataStoreService:GetDataStore("DataStore") local function saveData(plr) local dataTable = plr.leaderstats("Rank").Value local success, err = pcall(function() dataStore:SetAsync(plr.UserId, dataTable) -- Save the data with the player UserId, and the table we wanna save end) if success then -- If the data has been saved print("Data has been saved!") else -- Else if the save failed print("Data hasn't been saved!") warn(err) end end game.Players.PlayerAdded:Connect(function(plr) local leaderstats = Instance.new("Folder") leaderstats.Parent = plr leaderstats.Name = "leaderstats" local rank = Instance.new("StringValue") rank.Parent = leaderstats rank.Name = "Rank" local data -- We will define the data here so we can use it later, this data is the table we saved local success, err = pcall(function() data = dataStore:GetAsync(plr.UserId) -- Get the data from the datastore print("getting data...") end) if success then rank.Value = data else print("The player has no data!") end rank.Changed:Connect(function() print("rank changed") end) end) game.Players.PlayerRemoving:Connect(function(player) -- When a player leaves local success, err = pcall(function() saveData(player) -- Save the data end) if success then print("Data has been saved") else print("Data has not been saved!") end end)
You didn't assign any value to data
when you define it at Line 29
that's why it returned nil. rank.Value
at Line 36
has to be string. Hope this helps!
Success will be true even if there is no data. You will have to check if data exists as well before setting rank.Value
.
The other answers to this question are indeed telling you the mistake you made, but it does not look like they are being quite clear enough on how exactly to apply the fix. In short, all you need at the very least is an and
operator. However, I am going to go a little more in depth than that because I feel that this question stems from a lack of understanding of datastores. Let's go over this.
local data local success, err = pcall(function() data = dataStore:GetAsync(plr.UserId) print("getting data...") end) if success then rank.Value = data else print("The player has no data!") end
When making a datastore call like the above, the 'success' variable just indicates if the call made it over the network. So, you could ask for information from a datastore and you may find that the call is successful, but it doesn't mean that there is actually any data saved.
To elaborate on the why a datastore request might fail sometimes (and you might already know this!), when you ask for something over the network such as datastore information, that request has to make it over to Roblox's servers and hence could fail at times, usually because of a bad connection. The success variable tells you if it failed or not and that's its job. Again, it doesn't actually indicate that there is any saved data.
What you want to do is check if the call was successful AND if data was returned, and only then update your value object with the returned data.
if success and data then rank.Value = data else print("The player has no data OR the datastore request failed!") end
That's the fix. Very simple. Now, if you wish to handle datastore call failure in some way (retrying the request some number of times, etc.) you could take this a step further by firstly checking if the call was successful, then checking for the existence of saved data, like so:
if success then print("The datastore request was successful.") if data then print("Saved data found") else print("No saved data found") end else print("The datastore request failed: "..err") -- Print the error message to see why the call failed if you're curious! end