"Data stores can only accept valid UTF-8 characters."

hello everyone, i’m trying to make a code that saves my parts for my building game, i saved the properties in a table but when it begins to save this error “Data stores can only accept valid UTF-8 characters.” shows up and i really dont know what to do.

code:

local players = game:GetService("Players")
local dataStoreService = game:GetService("DataStoreService")
local autoSavingStore = dataStoreService:GetDataStore("F3XAutoSave")
local keyPrefix = "Player: "

local function save(player: Player)
	local key = keyPrefix .. tostring(player.UserId)
	local data = {}

	for i, obj: BasePart in ipairs(workspace:FindFirstChild("Builds"):WaitForChild(player.Name):GetDescendants()) do
		if obj:IsA("BasePart") then
			table.insert(data, {
				-- PART PROPERTIES
				obj.Name,
				obj.CanCollide,
				obj.CFrame.X,
				obj.CFrame.Y,
				obj.CFrame.Z,
				obj.Orientation.X,
				obj.Orientation.Y,
				obj.Orientation.Z,
				obj.Anchored,
				obj.Size.X,
				obj.Size.Y,
				obj.Size.Z,
				obj.Color.R,
				obj.Color.G,
				obj.Color.B,
				(string.match(tostring(workspace.Baseplate.TopSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.BottomSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.LeftSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.RightSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.BackSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.FrontSurface), "%.(%w+)$")),
				obj.Transparency,
				obj.Reflectance,
				string.match(tostring(obj.Material), "%.(%w+)$")
			})

			
	local success, err
	repeat
		success, err = pcall(function()
			autoSavingStore:SetAsync(key, function()
				return data
			end)
		end)
		
		task.wait()
	until success
	
	if not success then
		warn(tostring(err))
	end
end
	end
end
local function load(player: Player)
	local key = keyPrefix .. tostring(player.UserId)
	local success, err
	local data
	
	repeat
		success,err = pcall(function()
			data = autoSavingStore:GetAsync(key)
		end)
	until success or not players:FindFirstChild(player.Name)
	
	if not data then return end
	if success then
		for i, obj in ipairs(data) do
			local partInstance = Instance.new("Part")
			partInstance.Name=obj[1]
			partInstance.CanCollide=obj[2]
			partInstance.CFrame = CFrame.new(obj[3], obj[4], obj[5])
			partInstance.CFrame *= CFrame.Angles(math.rad(obj[6]),math.rad(obj[7]),math.rad(obj[8]))
			partInstance.Anchored=obj[9]
			partInstance.Size = Vector3.new(obj[10], obj[11], obj[12])
			partInstance.Color = Color3.new(obj[13],obj[14],obj[15])
			partInstance.TopSurface = Enum.SurfaceType[obj[16]]
			partInstance.BottomSurface = Enum.SurfaceType[obj[17]]
			partInstance.LeftSurface = Enum.SurfaceType[obj[18]]
			partInstance.RightSurface = Enum.SurfaceType[obj[19]]
			partInstance.BackSurface = Enum.SurfaceType[obj[20]]
			partInstance.FrontSurface = Enum.SurfaceType[obj[21]]
			partInstance.Transparency = obj[22]
			partInstance.Reflectance = obj[23]
			partInstance.Material = Enum.Material[obj[24]]
		end
	else
		warn(tostring(err))
	end
end

players.PlayerAdded:Connect(load)
players.PlayerRemoving:Connect(save)
game:BindToClose(function()
	for i, plr: Player in ipairs(players:GetPlayers()) do
		save(plr)
	end
end)

any help will be appreciated

2 Likes

Have you printed out what t tries to save prior to it getting to the SetAsync or whatever you are using? Check for any weird characters showing up in it

i tried to print(success) but it doesnt show anything, it just prints the error

I meant in one of these 3 places
image

i added “print(‘test’)” to these lines you told me to print into them, it prints the ‘test’ word with the errors.

No, removing a pcall and a repeat loop it will not fix the issue

Why are you saving the CFrame when you are also saving an orientation, instead save the vector3 instead.

No, print out the value of data

(also, don’t have function() return data end). Just have data)

Tom raised a point similar to what I think the actual issue is.

obj.CFrame.X,

I feel like it should actually be obj.CFrame.Position.X, or just obj.Position.X

1 Like

I had the same issue a couple months ago and found it helpful to instead save the vector3 and the orientation seperate and within a table.

			table.insert(data, {
				-- PART PROPERTIES
				obj.Name,
				obj.CanCollide,
				obj.Position.X,
				obj.Position.Y,
				obj.Position.Z,
				obj.Orientation.X,
				obj.Orientation.Y,
				obj.Orientation.Z,
				obj.Anchored,
				obj.Size.X,
				obj.Size.Y,
				obj.Size.Z,
				obj.Color.R,
				obj.Color.G,
				obj.Color.B,
				(string.match(tostring(workspace.Baseplate.TopSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.BottomSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.LeftSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.RightSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.BackSurface), "%.(%w+)$")),
				(string.match(tostring(workspace.Baseplate.FrontSurface), "%.(%w+)$")),
				obj.Transparency,
				obj.Reflectance,
				string.match(tostring(obj.Material), "%.(%w+)$")
			})

i changed the cframe to position and cframe.position but it doesnt seem to be working, i still get the error

ive changed this too but doesnt work

partInstance.Position = Vector3.new(obj[3], obj[4], obj[5])

im really sorry if you guys got annoyed for this.

1 Like

set it as the data instead of inserting, also partInstance.Position = Vector3.new(obj[3], obj[4], obj[5]) – im pretty sure that this wont work instead do this: Position = {X = obj[3], Y = obj[4], Z = obj[5]}

1 Like

It’s probably because you can’t save tables directly to DataStores.
Try wrapping the table in HttpService:JSONEncode(), which converts it into a string. When you load the table, use HttpService:JSONDecode() to return it to its original state.

may you tell me how should i do that?

you can save tables in a datastore.

Please read this quoted post. That’s why I’m saying this, correct me if I’m wrong.

You can save tables in a datastore but to you can also specifically convert something that can’t be saved in a datastore into JSONEncode().

1 Like

To save:

local success, err
	repeat
		success, err = pcall(function()
			autoSavingStore:SetAsync(key, function()
				return game:GetService("HttpService"):JSONEncode(data)
			end)
		end)
		
		task.wait()
	until success

To load:

local function load(player: Player)
	local key = keyPrefix .. tostring(player.UserId)
	local success, err
	local data
	
	repeat
		success,err = pcall(function()
			data = autoSavingStore:GetAsync(key)
		end)
	until success or not players:FindFirstChild(player.Name)
	
	if not data then return end
	if success then
		data = game:GetService("HttpService"):JSONDecode(data)

Hmm. I didn’t know that. Thanks

2 Likes