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

So I was working on my DataSave System but I got this error :

What does it mean?

Do you have any special characters or other text that might not be allowed? Try to check your scripts for any special characters that you might’ve accidentally put in.
Other than that, I’m not sure how this problem could be fixed.

2 Likes

The only characters allowed to be saved are


everything else cant be saved
(all this characters can be accessed trough string.char(number))

2 Likes

Can you take a look at my script? I cannot seem to figure out what’s wrong.

-- Services

local RS = game:GetService("ReplicatedStorage")
local TS = game:GetService("TweenService")
local PLRS = game:GetService("Players")
local SSS = game:GetService("ServerScriptService")
local SS = game:GetService("ServerStorage")
local LIGHTNING = game:GetService("Lighting")
local SG = game:GetService("StarterGui")
local SP = game:GetService("StarterPack")

----------------------------------------------

-- DataStore Variables

local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("DataStore")

----------------------------------------------

-- Variables

local TablePrinterModule = require(3148021300)

local Pets = game:GetService("ReplicatedStorage"):WaitForChild("Pets")
local PlayerPets = workspace:WaitForChild("Pets")

local HealthRemote = RS:WaitForChild("AttributeRemotes"):WaitForChild("AddHealth")
local SpeedRemote = RS:WaitForChild("AttributeRemotes"):WaitForChild("AddSpeed")
local AttackRemote = RS:WaitForChild("AttributeRemotes"):WaitForChild("AddAttack")
local MaxStaminaRemote = RS:WaitForChild("AttributeRemotes"):WaitForChild("AddMaxStamina")
local ResetRemote = RS:WaitForChild("AttributeRemotes"):WaitForChild("Reset")

----------------------------------------------

-- Attribute Variables

local StarterSpeed = game:GetService("ReplicatedStorage"):WaitForChild("CurrentWalkSpeed").Value
local StarterHealth = 100
local StarterJumpPower = 50
local starterMaxStamina = 100

local spdPerPoint = 0.5
local hpPerPoint = 10
local jumpPowerPerPoint = 1
local maxStaminaPerPoint = 10

local speedCap = 80
local jumpCap = 120

local HealthIncrementPerLevel = 5
local AttributeIncrement = 1

----------------------------------------------

-- Cancel Quest

local remote = game:GetService("ReplicatedStorage"):WaitForChild("QuestRemote")

remote.OnServerEvent:Connect(function(player, val)
	local questInfoF = player:WaitForChild("QuestInformation")
	if val == "CancelQuest" then
		for i, v in pairs(questInfoF:GetChildren()) do
			if v.className == "StringValue" then
				v.Value = "Default"
			elseif v.className == "IntValue" then
				v.Value = 0
			end
		end
	end
end)

----------------------------------------------------------------------------------------------

game.Players.PlayerAdded:Connect(function(player)
	
	-- Music
	
	player.PlayerGui:WaitForChild("GameMusic"):Play()

	-----------------
	
	-- Variables
	
	local playerID = player.UserId
	local character = player.Character
	local playerGui = player.PlayerGui
	
	-----------------
	
	-- Functions
	
	--[[    local function LoadPet(petValue)
		wait(6)
		if petValue.Value ~= "" then
			if Pets:FindFirstChild(petValue.Value) then
				local pet = Pets:FindFirstChild(petValue.Value):Clone()
				local petPosition = playerGui:WaitForChild("PetShop"):WaitForChild("Frame"):WaitForChild("ScrollingFrame"):FindFirstChild(petValue.Value):FindFirstChild("Buy"):FindFirstChild("PetPosition").Value
				pet.Name = player.Name
				pet.Parent = PlayerPets
				local function Follow(pet)
					local MovementAnimationTrack = pet:FindFirstChild("AnimationController"):FindFirstChild("Animator"):LoadAnimation(pet:FindFirstChild("Animations"):FindFirstChild("Movement"))
					local HumanoidRootPart = character:WaitForChild("HumanoidRootPart")
					local BodyPosition = Instance.new("BodyPosition", pet:WaitForChild("Pet"))
					BodyPosition.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
					local BodyGyro = Instance.new("BodyGyro", pet:WaitForChild("Pet"))
					BodyGyro.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
					character.Humanoid.Running:Connect(function(speed)
						if speed > 0 then
							MovementAnimationTrack:Play()
							MovementAnimationTrack:AdjustSpeed(3)
						end
						if speed <= 0 then
							MovementAnimationTrack:Stop()
							MovementAnimationTrack.TimePosition = 0
						end
					end)
					while wait() do
						BodyPosition.Position = HumanoidRootPart.Position + petPosition
						BodyGyro.CFrame = HumanoidRootPart.CFrame
						pet:WaitForChild("Pet").Orientation = HumanoidRootPart.Orientation + Vector3.new(0,180,0)
					end
				end
				Follow(pet)
			end
		end
	end ]]
	
	-----------------
		
	-- Folders
	
	local leaderstats = Instance.new("Folder", player)
	leaderstats.Name = "leaderstats"
	
	local weapon = Instance.new("Folder", player)
	weapon.Name = "Weapon"
	
	local attacks = Instance.new("Folder", weapon)
	attacks.Name = "WeaponAttacks"

	local projectiles = Instance.new("IntValue", leaderstats)
	projectiles.Name = "Projectiles"
	projectiles.Value = 0

	local currentProjectile = Instance.new("StringValue", leaderstats)
	currentProjectile.Name = "CurrentProjectile"
	currentProjectile.Value = "Shuriken"

	local QuestInformation = Instance.new("Folder", player)
	QuestInformation.Name = "QuestInformation"
	
	local attributes = Instance.new("Folder")
	attributes.Name = "Attributes"
	attributes.Parent = player
	
	local petBoostMultiplier = Instance.new("NumberValue", player)
	petBoostMultiplier.Name = "PetBoostMultiplier"
	petBoostMultiplier.Value = 1

	local hasReadTheTutorial = Instance.new("BoolValue", player)
	hasReadTheTutorial.Name = "HasReadTheTutorial"
	hasReadTheTutorial.Value = false

	local customizedCharacter = Instance.new("BoolValue", player)
	customizedCharacter.Name = "CustomizedCharacter"
	customizedCharacter.Value = false
	
	local loadingScreen = Instance.new("BoolValue", player)
	loadingScreen.Name = "LoadingScreen"
	loadingScreen.Value = false
	
	local ownsHouse = Instance.new("BoolValue", player)
	ownsHouse.Name = "OwnsHouse"
	ownsHouse.Value = false
	
	-----------------
	
	-- leaderstats
	
	local yen = Instance.new("IntValue", leaderstats)
	yen.Name = "Yen"
	yen.Value = 0
	
	local soulPoints = Instance.new("IntValue", leaderstats)
	soulPoints.Name = "Souls"
	soulPoints.Value = 0
	
	local Level = Instance.new("IntValue", leaderstats)
	Level.Name = "Level"
	Level.Value = 1
	
	local XP = Instance.new("IntValue", leaderstats)
	XP.Name = "XP"
	XP.Value = 0
	
	local MaxXP = Instance.new("IntValue", leaderstats)
	MaxXP.Name = "MaxXP"
	MaxXP.Value = 100
	
	local rebirths = Instance.new("IntValue", leaderstats)
	rebirths.Name = "Rebirths"
	rebirths.Value = 0
	
	local rebirthTokens = Instance.new("IntValue", leaderstats)
	rebirthTokens.Name = "RebirthTokens"
	rebirthTokens.Value = 0
	
	local rebirthYenBoost = Instance.new("IntValue", leaderstats)
	rebirthYenBoost.Name = "RebirthYenBoost"
	rebirthYenBoost.Value = 1
	
	local stamina = Instance.new("IntValue", leaderstats)
	stamina.Name = "Stamina"
	stamina.Value = 100
	
	local maxStamina = Instance.new("IntValue", leaderstats)
	maxStamina.Name = "MaxStamina"
	maxStamina.Value = 100
	
	local timePlayed = Instance.new("IntValue", leaderstats)
	timePlayed.Name = "Time Played"
	timePlayed.Value = 0
	
	local pet = Instance.new("StringValue", leaderstats)
	pet.Name = "Pet"
	pet.Value = "None"
	-- LoadPet(pet)
	
	-----------------

	-- Achievements
	
	local achievements = Instance.new("Folder", player)
	achievements.Name = "Achievements"
	
	local goldenShurikens = Instance.new("IntValue", achievements)
	goldenShurikens.Name = "GoldenShurikens"
	goldenShurikens.Value = 0
	
	-----------------
	
	-- Weapon
	
	local currentWeapon = Instance.new("StringValue", weapon)
	currentWeapon.Name = "CurrentWeapon"
	currentWeapon.Value = ""
	
	----------------
	
	-- QuestInfo
	
	local Title = Instance.new("StringValue", QuestInformation)
	Title.Name = "QuestTitle"
	Title.Value = "Default"

	local Task = Instance.new("StringValue", QuestInformation)
	Task.Name = "QuestTask"
	Task.Value = "Default"

	local Objective = Instance.new("IntValue", QuestInformation)
	Objective.Name = "QuestObjective"
	Objective.Value = 0

	local Progress = Instance.new("IntValue", QuestInformation)
	Progress.Name = "QuestProgress"
	Progress.Value = 0

	local Reward = Instance.new("IntValue", QuestInformation)
	Reward.Name = "QuestReward"
	Reward.Value = 0

	local Reward2 = Instance.new("IntValue", QuestInformation)
	Reward2.Name = "QuestReward2"
	Reward2.Value = 0
	
	-----------------
	
	-- IsUsingAttack Values
	
	local IsUsingAttack1 = Instance.new("BoolValue", attacks)
	IsUsingAttack1.Name = "IsUsingAttack1"
	IsUsingAttack1.Value = false
	
	local IsUsingAttack2 = Instance.new("BoolValue", attacks)
	IsUsingAttack2.Name = "IsUsingAttack2"
	IsUsingAttack2.Value = false
	
	local IsUsingAttack3 = Instance.new("BoolValue", attacks)
	IsUsingAttack3.Name = "IsUsingAttack3"
	IsUsingAttack3.Value = false
	
	local IsUsingAttack4 = Instance.new("BoolValue", attacks)
	IsUsingAttack4.Name = "IsUsingAttack4"
	IsUsingAttack4.Value = false
	
	local IsUsingAttack5 = Instance.new("BoolValue", attacks)
	IsUsingAttack5.Name = "IsUsingAttack5"
	IsUsingAttack5.Value = false
	
	local IsUsingAttack6 = Instance.new("BoolValue", attacks)
	IsUsingAttack6.Name = "IsUsingAttack6"
	IsUsingAttack6.Value = false

	local IsUsingAttack7 = Instance.new("BoolValue", attacks)
	IsUsingAttack7.Name = "IsUsingAttack7"
	IsUsingAttack7.Value = false

	-----------------
	
	-- Attributes
	
	local health = Instance.new("IntValue")
	health.Name = "Health"
	health.Parent = attributes
	health.Value = 0
	
	local attack = Instance.new("IntValue")
	attack.Name = "Attack"
	attack.Parent = attributes
	attack.Value = 0
	
	local speed = Instance.new("IntValue")
	speed.Name = "Speed"
	speed.Parent = attributes
	speed.Value = 0
	
	local maximumStamina = Instance.new("IntValue")
	maximumStamina.Name = "MaximumStamina"
	maximumStamina.Parent = attributes
	maximumStamina.Value = 0
	
	-----------------
	
	-- Player's Weapon Names
	
	local WeaponNames = Instance.new("Folder", player)
	WeaponNames.Name = "WeaponNames"
	
	-----------------
	
	-- Gamepasses
	
	local Gamepasses = Instance.new("Folder")
	Gamepasses.Name = "Gamepasses"
	Gamepasses.Parent = player
	
	local InventorySlots = Instance.new("IntValue")
	InventorySlots.Name = "InventorySlots"
	InventorySlots.Parent = Gamepasses
	InventorySlots.Value = 3
	
	-----------------
	
	-- Avatar
	
	local Avatar = Instance.new("Folder")
	Avatar.Parent = player
	Avatar.Name = "Avatar"
	
	local Hair = Instance.new("StringValue")
	Hair.Parent = Avatar
	Hair.Name = "Hair"
	
	-----------------
	
	-- Attribute Points

	local function PointsAvailable(player)
		local PointsUsed = player.Attributes.Health.Value + player.Attributes.Speed.Value + player.Attributes.Attack.Value + player.Attributes.MaximumStamina.Value
		local PointsAvailable = player.leaderstats.Level.Value - PointsUsed
		return PointsAvailable > 0
	end

	HealthRemote.OnServerEvent:Connect(function(player)
		player.Attributes.Health.Value += AttributeIncrement
		player.Character.Humanoid.MaxHealth = StarterHealth + (player.leaderstats.Level.Value * HealthIncrementPerLevel) + (player.Attributes.Health.Value * hpPerPoint)
		player.Character.Humanoid.Health = StarterHealth + (player.leaderstats.Level.Value * HealthIncrementPerLevel) + (player.Attributes.Health.Value * hpPerPoint)
	end)

	SpeedRemote.OnServerEvent:Connect(function(player)
		if player.Attributes.Speed.Value < speedCap then
			player.Attributes.Speed.Value += AttributeIncrement
			player.Character.Humanoid.WalkSpeed = StarterSpeed + (player.Attributes.Speed.Value * spdPerPoint)
		end
	end)

	AttackRemote.OnServerEvent:Connect(function(player)
		player.Attributes.Attack.Value += AttributeIncrement
	end)

	MaxStaminaRemote.OnServerEvent:Connect(function(player)
		player.Attributes.MaximumStamina.Value += AttributeIncrement
		player.leaderstats.Stamina.Value += maxStaminaPerPoint
		player.leaderstats.MaxStamina.Value += maxStaminaPerPoint
	end)

	ResetRemote.OnServerEvent:Connect(function(player)
		player.Attributes.Health.Value = 0
		player.Attributes.Attack.Value = 0
		player.Attributes.Speed.Value = 0
		player.Attributes.MaximumStamina.Value = 0
		player.Character.Humanoid.MaxHealth = StarterHealth + (player.leaderstats.Level.Value * HealthIncrementPerLevel) + (player.Attributes.Health.Value * hpPerPoint)
		player.Character.Humanoid.Health = StarterHealth + (player.leaderstats.Level.Value * HealthIncrementPerLevel) + (player.Attributes.Health.Value * hpPerPoint)
		player.Character.Humanoid.WalkSpeed = (StarterSpeed + player.Attributes.Speed.Value * spdPerPoint)
		player.leaderstats.MaxStamina.Value = starterMaxStamina
		player.leaderstats.Stamina.Value = starterMaxStamina
	end)
	
	-----------------
	
	--[[ Formulas
	
	RealHP = StarterHealth + (Level.Value * HealthIncrementPerLevel) + (health.Value * hpPerPoint)
	
	
	
	-----------------
	
	
	-- Level Up

	XP:GetPropertyChangedSignal('Value'):Connect(function()
	--	repeat
			if XP.Value >= MaxXP.Value then
				Level.Value += 1
				XP.Value -= MaxXP.Value
				MaxXP.Value *= 1.25
				character.Humanoid.MaxHealth = (Level.Value * HealthIncrementPerLevel) + (health.Value * hpPerPoint)
			end
	--	until XP.Value < MaxXP.Value
	end)
	
	]]
	
	-----------------
	
	-- Quest Reward
	
	local rewarded = false

	Title.Changed:Connect(function()
			Progress.Changed:Connect(function()
			if Progress.Value >= Objective.Value and rewarded == false then
				rewarded = true
				local function GiveReward()
					player:WaitForChild("leaderstats"):WaitForChild("Yen").Value += Reward.Value
					player:WaitForChild("leaderstats"):WaitForChild("XP").Value += Reward2.Value
					Title.Value = "Default"
					Task.Value = "Default"
					Progress.Value = 0
					Objective.Value = 0
					Reward.Value = 0
					Reward2.Value = 0
					player:WaitForChild("PlayerGui"):WaitForChild("Notifications"):WaitForChild("CompletedQuest").Visible = true
					wait(2)
					player:WaitForChild("PlayerGui"):WaitForChild("Notifications"):WaitForChild("CompletedQuest").Visible = false
				end
				GiveReward()
				wait(0.001)
				remote:FireClient(player, "CancelQuest")
				wait(0.5)
				rewarded = false
			end
		end)
	end)
	
	-----------------

	-- DataStore

	local data

	local Success, ErrorMessage = pcall(function()
		data = DataStore:GetAsync(playerID)
	end)

	if Success then
		player.leaderstats.Yen.Value = data.Yen -- Saves
		player.leaderstats.Souls.Value = data.Souls -- Saves
		player.leaderstats.Level.Value = data.Level -- Saves
		player.leaderstats.Rebirths.Value = data.Rebirths -- Saves
		player.leaderstats.RebirthTokens.Value = data.RebirthTokens -- Saves
		player.leaderstats.RebirthYenBoost.Value = data.RebirthYenBoost -- Saves
		player.PetBoostMultiplier.Value = data.PetBoostMultiplier -- Saves
		player.leaderstats["Time Played"].Value = data.TimePlayed -- Saves
		
		player.Achievements.GoldenShurikens.Value = data.GoldenShurikens -- Saves
		
		player.Attributes.Health.Value = data.Health -- Saves
		player.Attributes.Speed.Value = data.Speed -- Saves
		player.Attributes.Attack.Value = data.Attack -- Saves
		player.Attributes.MaximumStamina.Value = data.MaximumStamina -- Saves
		
		player.leaderstats.MaxStamina.Value = data.MaxStamina -- Saves
		
		player.Weapon.CurrentWeapon.Value = data.CurrentWeapon -- Saves
		
		player.leaderstats.Pet.Value = data.Pet -- Saves
		
		player.OwnsHouse.Value = data.House -- Saves
		
		player.Avatar.Hair.Value = data.Hair -- Saves
		
		player.leaderstats.Projectiles.Value = data.Projectiles -- Saves
		player.leaderstats.CurrentProjectile.Value = data.CurrentProjectile -- Saves
		
		player.Gamepasses.InventorySlots.Value = data.InventorySlots
		
		player.QuestInformation.QuestTitle.Value = data.QuestTitle -- Saves
		player.QuestInformation.QuestTask.Value = data.QuestTask -- Saves
		player.QuestInformation.QuestObjective.Value = data.QuestObjective -- Saves
		player.QuestInformation.QuestProgress.Value = data.QuestProgress -- Saves
		player.QuestInformation.QuestReward.Value = data.QuestReward -- Saves
		player.QuestInformation.QuestReward2.Value = data.QuestReward2 -- Saves
		
		player.CustomizedCharacter.Value = data.CustomizedCharacter -- Saves
		player.HasReadTheTutorial.Value = data.HasReadTheTutorial -- Saves
		
		player.leaderstats.MaxXP.Value = data.MaxXP
		player.leaderstats.XP.Value = data.XP
	else
		print("An error has occured whilst loading your data.")
		warn(ErrorMessage)
	end
end)

-------------------------------------------------------------------

-- Save Player's Data

game.Players.PlayerRemoving:Connect(function(player)
	
	local Data = {
		Yen = player.leaderstats.Yen.Value, -- Saves
		Souls = player.leaderstats.Souls.Value, -- Saves
		Level = player.leaderstats.Level.Value, -- Saves
		Rebirths = player.leaderstats.Rebirths.Value, -- Saves
		RebirthTokens = player.leaderstats.RebirthTokens.Value, -- Saves
		RebirthYenBoost = player.leaderstats.RebirthYenBoost.Value, -- Saves
		PetBoostMultiplier = player.PetBoostMultiplier.Value, -- Saves
		TimePlayed = player.leaderstats["Time Played"].Value, -- Saves
		
		GoldenShurikens = player.Achievements.GoldenShurikens.Value, -- Saves
		
		Health = player.Attributes.Health.Value, -- Saves
		Speed = player.Attributes.Speed.Value, -- Saves
		Attack = player.Attributes.Attack.Value, -- Saves
		MaximumStamina = player.Attributes.MaximumStamina.Value, -- Saves
		
		MaxStamina = player.leaderstats.MaxStamina, -- Saves
		
		CurrentWeapon = player.Weapon.CurrentWeapon.Value, -- Saves
		
		Pet = player.leaderstats.Pet.Value, -- Saves
		
		House = player.OwnsHouse.Value, -- Saves
		
		Hair = player.Avatar.Hair.Value, -- Saves
		
		Projectiles = player.leaderstats.Projectiles.Value, -- Saves
		CurrentProjectile = player.leaderstats.CurrentProjectile.Value, -- Saves
		
		InventorySlots = player.Gamepasses.InventorySlots.Value,
		
		QuestTitle = player.QuestInformation.QuestTitle.Value, -- Saves
		QuestTask = player.QuestInformation.QuestTask.Value, -- Saves
		QuestObjective = player.QuestInformation.QuestObjective.Value, -- Saves
		QuestProgress = player.QuestInformation.QuestProgress.Value, -- Saves
		QuestReward = player.QuestInformation.QuestReward.Value, -- Saves
		QuestReward2 = player.QuestInformation.QuestReward2.Value, -- Saves
		
		CustomizedCharacter = player.CustomizedCharacter.Value, -- Saves
		HasReadTheTutorial = player.HasReadTheTutorial.Value, -- Saves
		
		MaxXP = player.leaderstats.MaxXP.Value,
		XP = player.leaderstats.XP.Value
	}

	local Success, ErrorMessage = pcall(function()
		DataStore:SetAsync(player.UserId, Data)
	end)

	if Success then
		print("Data successfully saved!")
		print(TablePrinterModule(Data))
	else
		print("An error has occured whilst loading your data.")
		warn(ErrorMessage)
	end
	
end)

------------

-- DataStore in-studio

game:BindToClose(function()
	if game:GetService('RunService'):IsStudio() then
		wait(2)
	end
end)

------------

--[[ Load House

local function LoadHouse(player)
	wait(4)
	local remote = SG:WaitForChild("HouseSystem"):WaitForChild("LoadHouseRemote")
	remote:FireAllClients()
end

PLRS.PlayerAdded:Connect(LoadHouse)

------------

-- Load Accessories

local function LoadAccessories(player)
	wait(4)
	for i, values in pairs(player.Avatar:GetChildren()) do
		if values.Value ~= "" then
			RS:FindFirstChild(values.Name.."s"):FindFirstChild(values.Value):Clone().Parent = player.Character
		end
	end
end

PLRS.PlayerAdded:Connect(LoadAccessories)

------------

-- Setup Values

	local function SetupHealth(character)
		local humanoid = character.Humanoid
	humanoid.MaxHealth = StarterHealth + (Level.Value * HealthIncrementPerLevel) + (health.Value * hpPerPoint)
	wait(0.25)
	humanoid.Health = humanoid.MaxHealth
	end
local function SetupSpeed(character)
	local humanoid = character.Humanoid
	humanoid.WalkSpeed = StarterSpeed + speed.Value
end

SetupSpeed(character)

player.CharacterAdded:Connect(SetupSpeed)
player.CharacterAdded:Connect(SetupHealth)


]]

MaxStamina is missing the .Value at the end so is trying to store the Instance.

MaxStamina = player.leaderstats.MaxStamina
2 Likes

Datastores aren’t practical to work with, and don’t allow straight storage of dictionaries/arrays/tables because of it.

I personally get around this by json encoding them before saving to the datastore, and just decoding when loading them. (Note: I believe this is normal practice, however when I was looking around for this exact thing I found very little information on it, so I have no idea if this is the best way to handle datastores or not)

HttpService has a feature called “JSONEncode” (HttpService:JSONEncode(content)) which does exactly what it sounds like, converts whatever is fed into it in one long json friendly string which can in turn be saved into a datastore with zero issues.

How I write to a datastore:
DataStore:SetAsync(Key, HttpService:JSONEncode(BigTableOfData))

How I read from a datastore:
local toReturn = HttpService:JSONDecode(DataStore:GetAsync(Key))
return toReturn

3 Likes

Use json:encode you cant store a dictionary

1 Like

Oh thank you so much!
You saved my life!
<3

2 Likes