The most idiotic bug i've seen yet. Datastores work on my other games but not a certain one

Roblox has outdone itself for making my life harder. Hello developers, i am making a game but the datastores always have to mess it up. This time, i cannot do anything. This datastore breaks on this on certain game i’ve made, but if i go to a other game and do it there, it works like a charm?

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local isStudio = RunService:IsStudio()
local DataStoreService = game:GetService("DataStoreService")
local ds = DataStoreService:GetDataStore("LeaderStatSave")

local temporalData = {}
local abilities = {
	"Boost",
	"Heal",
	"Engineer",
	"Divine"
}


Players.PlayerAdded:Connect(function(plr)
	local leader = Instance.new("Folder")
	leader.Name = "leaderstats"

	local private = Instance.new("Folder")
	private.Name = "PrivateStats"

	local Coins = Instance.new("NumberValue", leader)
	Coins.Name = "Coins"

	local Wins = Instance.new("NumberValue", leader)
	Wins.Name = "Wins"

	leader.Parent = plr

	temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

	if temporalData[plr.UserId].Abilities == nil then
		temporalData[plr.UserId].Abilities = {} -- bug
	end

	for _, ability in ipairs(abilities) do
		if temporalData[plr.UserId].Abilities[ability] == nil then
			temporalData[plr.UserId].Abilities[ability] = false
		end
		local bool = Instance.new("BoolValue")
		bool.Name = ability
		bool.Value = temporalData[plr.UserId].Abilities[ability]
		bool:GetPropertyChangedSignal("Value"):Connect(function()
			temporalData[plr.UserId].Abilities[ability] = bool.Value
		end)
		bool.Parent = private
	end

	private.Parent = plr

	Coins.Value = temporalData[plr.UserId].Coins or 0
	Coins:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Coins = Coins.Value
	end)

	Wins.Value = temporalData[plr.UserId].Wins or 0
	Wins:GetPropertyChangedSignal("Value"):Connect(function()
		temporalData[plr.UserId].Wins = Wins.Value
	end)

	plr.AncestryChanged:Connect(function()
		if plr:IsDescendantOf(game) or temporalData[plr.UserId] == nil then
			return
		end
		if isStudio then
			print("Data not saved because it runs in Studio")
			return
		end
		local s, err = pcall(function()
			ds:UpdateAsync(plr.UserId, function()
				return temporalData[plr.UserId]
			end)
		end)
		if s ~= true then
			warn("Failed saving data for player: " .. plr.Name .. ", key: " .. plr.UserId .. "\n" .. tostring(err))
		else
			print("Data saved for player: " .. plr.Name)
		end
		temporalData[plr.UserId] = nil
	end)
end)

Error code:
image

Honestly, is this ROBLOX’s fault or am i doing something wrong here. This is really really ANNOYING.

3 Likes

You are attempting to find Abilities in a string.

Try printing temporalData[plr.UserId] because datastore:GetAsync(userId) is returning a string.

1 Like

My problem is, why is it working for other games but not this certain one?

2 Likes

That’s not true, you have saved a string to the userId you’re using for testing and now you have to clear it using the command bar or a data store editor.

1 Like

You’re saying i have to clear it?

1 Like

You have to save a table to the data store because it is a string now.

local data = ds:GetAsync(plr.UserId) -- returns a string
print(type(data)) -- string

You have to use a data store editor to set the data or use the command bar and type

game.DataStoreService:GetDataStore("LeaderStatSave"):SetAsync(YOURUSERID, nil)

which will wipe the data off your userId

I’d also suggest using Players.PlayerRemoving instead of player.AncestryChanged
because PlayerRemoving fires before the player leaves, while the other after the player leaves.

Maybe you didn’t turn api on??

I have. It’s just extremely weird, i could send a video of showing the thing.

Where do i put

local data = ds:GetAsync(plr.UserId) -- returns a string
print(type(data)) -- string

exactly?

You don’t put that anywhere.
I was just showing you what the output would print.
What you are doing is

local data = "somerandomstring" or {}
-- it will pick "somerandomstring" because it isn't false or nil ,it's a string

which means that:

data.Abilites 

is the same as

"somerandomstring".Abilities

which would of course error.

game:GetService("Players").PlayerAdded:Connect(function(player)
 game.DataStoreService:GetDataStore("LeaderStatSave"):SetAsync(player.UserId, nil)
end)

put this code in a different script and run the game, after that delete the script

1 Like
temporalData[plr.UserId] = ds:GetAsync(plr.UserId) or {}

which is the same as

temporalData[plr.UserId] = "" or {}

If you don’t get it with that example
I don’t know what the string actually is so I’m referring to it with ""

1 Like
ServerScriptService.Main:Data:37: attempt to index nil with 'Boost'

erroring on

if temporalData[plr.UserId].Abilities[ability] == nil then

My bad I mean the Abilities table doesn’t exist

1 Like

Now temporalData[plr.UserId].Abilities is nil.

1 Like

It does.

local abilities = {
	"Boost",
	"Heal",
	"Engineer",
	"Athletic"
}

okay nevermind just look at the reply below

1 Like

temporalData[plr.UserId].Abilities is nil.
You are looking for a value of table abilities in temporalData[plr.UserId].Abilities which actually means you are looking in nil
temporalData[plr.UserId].Abilities[ability]
is
nil[ability] which errors

2 Likes

So, what do i do exactly…? I’m a bit confused.

You have to set temporalData[plr.UserId].Abilities to a table

which you do here, but it doesn’t run for some reason.
Possibly temporalData[plr.UserId].Abilities == nil is false.
Try printing temporalData[plr.UserId].Abilities and tell me what gets printed

i got nill. i guess you were right