API service is enabled but is not showing Leaderboard

Today I have enabled the API service on my Roblox game settings and created a leaderboard to show how many coins I gave on my game.

This is my script. It is a regular script placed in Serverscriptservice.

local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore("Coins")

game.Players.PlayerAdded:Connect(function(player)
	local leaderboard = Instance.new("Folder",player)
	leaderboard.Name = "Leaderboard"
	
	local coins = Instance.new("IntValue",leaderboard)
	coins.Name = "Coins"
	coins.Value = 25
	
	local recieved,failed = pcall(function()
		data = dataStore:GetAsync("User-"..player.UserId)
	end)
	
	if recieved then
		coins.Value = data[1]
		print("Data was recieved")
	else
		print("Data was not recieved")
	end
	
	while true do wait(30)
		dataStore:SetAsync("User-"..player.UserId,{coins.Value})
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local leaderboard = player.Leaderboard
	local coins = leaderboard.Coins
	
	local saved,failed = pcall(function()
		dataStore:SetAsync("User-"..player.UserId,{coins.Value})
	end)
	
	if saved then
		print("Data was saved")
	else
		print("Data was not saved")
	end
end)

I checked the output and I got a message saying:
“Data was received”

I am pretty sure that the data had worked but my leaderboard still wasn’t showing up after enabling API because I made a print, making it say data was received if the data was received.

I really hope this can get solved/ find the issue because no one would want to collect coins without knowing how much they have.

I can not send any photos at this stage and this is the most I know about this issue/ script.

I hope I did not send this in the wrong category because I don’t know if this is a Roblox bug or if I am scripting something wrong.

Thank you for reading.

Hey there! Try doing this when loading data:

local recieved, result = pcall(function()
   local data = dataStore:GetAsync("User-"..player.UserId)
   return data
end)

if received then
   print('Loaded')
   coins.Value = result[1] or 0  -- if everything worked, "result" will be the value returned (the data)
else
   print('Failed')
   warn(result)  -- if it fails, "result" will be the error message
   player:Kick('Avoiding dataloss')  -- this is a good practice, but make sure to check if player's data has loaded before saving it
end

And please remove that:

while true do wait(30)
   dataStore:SetAsync("User-"..player.UserId,{coins.Value})
end

Save the data only when the player leaves.

5 Likes

I just tried this. I am getting an error saying:

Disconnected
You were kicked from this game: Avoiding Dataloss
(Error Code: 267)
This happened right when I joined the game.

Thanks for trying

Is there something else in the output? It should warn the error message.

Yes. There is an error in the output saying:

Server Kick Message: You were kicked from this game: Avoiding Dataloss.

Ok lol, try to remove this line:

player:Kick('Avoiding dataloss')  

And check the output

SORRY, I just typed wrong, please replace:

local received, result = pcall(function()
   local data = dataStore:GetAsync("User-"..player.UserId)
   return data
end)
1 Like

I tried removing

player:Kick("Avoiding datalosss')

and I also replaced

   local data = dataStore:GetAsync("User-"..player.UserId)
   return data
end)

and I also renamed it to Leaderstats. Nothing is happening in the game or in the output. The player kick was not there anymore but nothing happened. There are no red lines either.

Rename to “leaderstats” (lowercase)

Is the output completely empty? Because the error message should be in orange

@GAFFAL_1236 I renamed it to leaderstats in lowercase and I am not getting any orange error messages in the output.

What is in output, “Loaded” or “Failed”?

It is very strange. I am not getting any of these. The only line I got from the leaderboard script was a “Data was recieved”

Can you send the whole script?
But that’s great, it means there was no problem when requesting data.

1 Like

I hope I didn’t type something wrong the whole time but here is my whole script. Like i said, it is a regular script in ServerScriptService.

local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetDataStore("Coins")

game.Players.PlayerAdded:Connect(function(player)
	local leaderboard = Instance.new("Folder",player)
	leaderboard.Name = "Leaderboard"
	
	local coins = Instance.new("IntValue",leaderboard)
	coins.Name = "Coins"
	coins.Value = 25
	
	local recieved,failed = pcall(function()
		data = dataStore:GetAsync("User-"..player.UserId)
	end)
	
	if recieved then
		coins.Value = data[1]
		print("Data was recieved")
	else
		print("Data was not recieved")
	end
end)
local received, result = pcall(function()
   local data = dataStore:GetAsync("User-"..player.UserId)
   return data
end)

game.Players.PlayerRemoving:Connect(function(player)
	local leaderboard = player.Leaderboard
	local coins = leaderboard.Coins
	
	local saved,failed = pcall(function()
		dataStore:SetAsync("User-"..player.UserId,{coins.Value})
	end)
	
	if saved then
		print("Data was saved")
	else
		print("Data was not saved")
	end
end)
1 Like

Rename the folder from “Leaderboard” to “leaderstats”

local leaderboard = Instance.new("Folder",player)
leaderboard.Name = "leaderstats"

There are also some errors when loading data.
I’m extremely sorry, but I have to go to bed, t’s 3 am in the country I leave. But I’ll bookmark this and come back tomorrow :slight_smile:

1 Like

I did this already. Thanks for helping me. I might not be online tomorrow so that is fine. Btw, the script is just a script. It is not a folder and the script doesn’t have anything inside it. Thanls for helping me once more :slight_smile:.

2 Likes

Hiwi! o/

So u fixed it? Thats great!. What was the problem?
Just some comments about it. Why using "User-"..player.UserId ? I think its enough to leave it like player.UserId. Its a number that never repeats among players, its keeping it simple, no need to add “User-”.
Why storing an array? {coins.Value} ? I think its enough by only storing coins.Value without the brackets, so you are storing an int value not an array. If you use the array, you could have more space to store things, so its a good idea tho, but, for quick tests, just saving an int value is more reliable.

When I use datastores, usually the Studio fails if I try to save the datastore on PlayerRemoving(). Usually it get fixed it when u publish the project and try again. If you try to test it without publishing any change you made, idk why, Studio fails on saving the datastore. So be sure to publish ur project, and test it a couple of times before it works fine.

Last thing, you can make some debugging by just adding a couple of buttons on workspace, and testing the behaviour while saving the datastore, checking the output, to be sure you are doing things right.

I checked ur post, and I wanted to create a quick example for you to check about the debugging, and making a little changes to ur script, hope it helps :3
DataCoins.rbxl (30.1 KB)

This is a part of the script inside the file I sent you. Its working fine for me (if it doesnt work for you, probably is the Studio bug I told you, or maybe the DataStore API still off, you said u turned it on, but its a good idea to double check):

local dataStoreService = game:GetService("DataStoreService")
local coinsData = dataStoreService:GetDataStore("Coins")

----- MAIN ON JOIN AND LEAVE FUNCTIONS
-- On player added check if has coins, if not, give them 25
game.Players.PlayerAdded:Connect(function(player)
	local leaderboard = Instance.new("Folder",player)
	leaderboard.Name = "leaderstats"

	local coins = Instance.new("IntValue",leaderboard)
	coins.Name = "Coins"

	local success, currentCoins = pcall(function()
		return coinsData:GetAsync(player.UserId)
	end)

	if success then
		coins.Value = currentCoins
		print("You have coins: ", currentCoins)
	else
		print("No coins in your account")
		coins.Value = 25
	end
end)

-- On player left game, save their coins into his account
game.Players.PlayerRemoving:Connect(function(player)
	local leaderboard = player.leaderstats
	local coins = leaderboard.Coins

	local success, err = pcall(function()
		coinsData:SetAsync(player.UserId, coins.Value)
	end)

	if success then
		print(coins.Value, "Coins Saved into ur account")
	end
end)

If you still want to use an array to store the coins. Heres another file storing the array into the datastore:
DataCoins.rbxl (30.1 KB)

1 Like

Hey! This code should work pretty well, but there’s a problem here:

if success then
    coins.Value = currentCoins
	print("You have coins: ", currentCoins)
else
	print("No coins in your account")  -- it's not true, the data failed to load
	coins.Value = 25
end

This would be better:

if success then

   if currentCoins then
      coins.Value = currentCoins
      print("You have coins: ", currentCoins)
   else
      print("No coins in your account")
      coins.Value = 25
   end

else
	warn("failed to load")
end
1 Like

Yup I agree, but not completely.
Actually in terms of efficiency, its better to retry the GetAsync() if the error occurs.
Set a max amount of retries, if the error continues, handle the error, by teleporting the player to another place and bring it back to the main game again for more retries, or kick the player or any way u wanna handle it. Something like this

game.Players.PlayerAdded:Connect(function(player)
	local leaderboard = Instance.new("Folder",player)
	leaderboard.Name = "leaderstats"

	local coins = Instance.new("IntValue",leaderboard)
	coins.Name = "Coins"

	local success, currentCoins = pcall(function()
		return coinsData:GetAsync(player.UserId)
	end)

	if not success then
		-- Retry holder count
		local retry = 0

		-- Retry 5 times with 1 second delay
		while retry < 5 do
			success, currentCoins = pcall(function()
				return coinsData:GetAsync(player.UserId)
			end)
			
			-- If error happens
			if not success then
				wait(1)
			else 
				break -- Break the thread continue with script
			end
		end
	end

--[[ if everything is fine set the coins, otherway handle the error ]]
	if success then
		if currentCoins then
			-- If no error and coins found, set the coins
			coins.Value = currentCoins
			print("You have coins: ", currentCoins)
		else
			-- If no error call and player has no coins, is a new player give coins
			print("No coins in your account")
			coins.Value = 25
		end
	else
		print("Error")
		--[[ Teleport the player to another place, wait there a few seconds
		then teleport it back again into the main game to try again	]] 
	end
end)

You know, maybe even adding some warnings to the player, to let them know whats happening. But yup, its just about more implementation on how to properly handle a possible error on the GetAsync() and actually using SetAsync() is not reliable either. Would be better UpdateAsync()

I didnt tested this last code, hope theres no typos, and its a little hard to test the error handling, due to its impossible to know when its gonna happen an error or not on getting the datastore. Its “easy” to cause an error by using studio, make some changes to the scripts and test it without saving, so maybe studio will fail to connect with the datastore, so that helps in testing the error handling and retries.

2 Likes