Cannot store Dictionary in data store. Data stores can only accept valid UTF-8 characters

I’m trying to get the hang of saving data for my game, I copied this code and modified it a little to suit me however I get the error I put in the title, this is the code I have

local dataStoreService = game:GetService("DataStoreService")
local saveData = dataStoreService:GetDataStore("playerStants")

game.Players.PlayerAdded:Connect(function(player)
	local power = game.ReplicatedStorage.PlayerStats.power
	power.Value = 0
	
	local playerId = "Player_".. player.UserId
	local data = saveData:GetAsync(playerId)
	
	if data then
		power.Value = data['Power']
	else
		power.Value = 0
	end	
end)

game.Players.PlayerRemoving:Connect(function(player)
	local dataToSave = {
		power = game.ReplicatedStorage.PlayerStats.power
	}
	local playerId = "Player_".. player.UserId
	local success, err = pcall(function()
		saveData:SetAsync(playerId, dataToSave)
	end)
	
	if success then
		print("data saved")
	else
		print("data failed to save")
	end

end)
1 Like

Judging by this…

youre trying to save a value instance to the datastore here

try this maybe?

local dataToSave = {
		power = game.ReplicatedStorage.PlayerStats.power.Value
	}

well you did fix the error, but the data still isnt saving

Because there’s an indexing mismatch. You save it as power, but you’re asking for Power. When indexing dictionaries, caps matter.

Change “Power” to “power” here

When you are saving the data the power variable is all lowercase, but when you load the data you are using an uppercase P “Power” instead of what you saved, “power”

So try changing the value in the quotes into ‘power’

1 Like

I changed it to all lower case and now atleast I am getting the print that data was saved but its still at 0 when loading into the game

Try using a pcall and an empty variable.

local data

local success, errorMessage = pcall(function()
    data = saveData:GetAsync(playerId)
end)

if success then
    if data['power'] == nil then
        power.Value = 0
    end
    power.Value = data['power']
else
    print(errorMessage)
end

Try using this instead of using a variable to call the datastore

I implemented everything into the code but I still dont get any message or have the data be saved

local dataStoreService = game:GetService("DataStoreService")
local saveData = dataStoreService:GetDataStore("playerStants")

local players = game:GetService("Players")

game.Players.PlayerAdded:Connect(function(player)
	local power = game.ReplicatedStorage.PlayerStats.power
	local data 
	local playerId = "Player_".. player.UserId
	
	local success, errorMessage = pcall(function()
		data = saveData:GetAsync(playerId)
	end)

	if success then
		if data['power'] == nil then
			power.Value = 0
		end
		power.Value = data['power']
	else
		print(errorMessage)
	end
	
	if data then
		power.Value = data['power']
		print("there is data saved")
		print(power.Value)
	else
		power.Value = 0
		print("no data")
	end	
end)


game.Players.PlayerRemoving:Connect(function(player)
	local dataToSave = {
		power = game.ReplicatedStorage.PlayerStats.power.Value
	}
	local playerId = "Player_".. player.UserId
	local success, err = pcall(function()
		saveData:SetAsync(playerId, dataToSave)
	end)

	if success then
		print("saved data")
	else
		print(err)
	end
end)

Delete this part, and I’m confused by what you mean by saving because loading and saving data are 2 different things, and what message is not showing

And in the player removing function does it print “saved data”?

yes, it does print that the data was saved

yeah, no it still doesnt save the data, even though it prints it did

Are you changing the value on the client and not on the server by chance?
Any changes you do on the client won’t automatically replicate to the server.
Editing your stat on the client therefore won’t change it on the server.
(While playtesting; you are on the client by default until you switch to server)

You might me onto something there, the value is located in replicated storage but its only changed by the local scripts

Yeah; if local scripts change the value; the server won’t be able to see these changes, consider making a script on the server to change these values. You can use RemoteEvents or RemoteFunctions to communicate towards the server. (If actions on the client are necessary to trigger these)

the value is supposed to be separate for every player, wont that mean that if I change it it will also change it for other players?

You will have to make different values or “PlayerStats” in your case for each player. Rename each of such folders to an identifier like the UserId using the same one for all players indeed makes all players use the same data which causes problems.

I’m curious if it would be easier to just move the value into starter character scripts if that will work?

It would be easy to create a value inside of the player, not sure if in StarterPlayerScripts works; but you can try to do so. StarterCharacterScripts however is not recommended to put any value inside that needs to be retained as any starter character scripts usually get reset after the user respawns.
A lot of games make use of leaderstats inside of their Player to replicate the status of their stats

wont that display their stats for all their other people in the server?

If you want to display the stats of each player to all players; call the folder leaderstats, any other name will make Roblox not automatically visualise it. You can also make a custom gui to show stats for a user.