ProfileService: How can I get a profile back upon wiping it

I’m trying to make my leveling system but my profileservice is broken. My player joins in and they are greeted with “ServerScriptService.Server.PlayerData:85: Profile does not exist for 471263686” in the output. The player won’t save their level or any values in their profile because it was wiped.

Profile Service Script
local Bindables = game.ReplicatedStorage.Bindables

local PlayerData = {}

local dataTemplate = {
	Money = 0,
	Abilities = {},
	Equipped = "",
	Wins = 0,
	Kills = 0,
	Level = 1,
	Experience = 0, -- divided by 3 and multiply 3 every level
}

local ProfileService = require(script.ProfileService)
local Leaderstats = require(script.Leaderstats)
local Leaderboards = require(script.Leaderboards)

local Players = game:GetService("Players")

local ProfileStore = ProfileService.GetProfileStore(
	"PlayerProfile",
	dataTemplate
)

local Profiles = {}

local function playerAdded(player)
	local profile = ProfileStore:LoadProfileAsync("Player_"..player.UserId)
	print(profile)
	if profile then
		profile:AddUserId(player.UserId)
		profile:Reconcile()
		
		profile:ListenToRelease(function()
			Profiles[player] = nil
			
			player:Kick()
		end)
		
		if not player:IsDescendantOf(Players) then
			profile:Release()
		else
			Profiles[player] = profile
			Leaderstats:Init(player,profile,PlayerData)
		end
	else
		player:Kick()
	end
	while true do
		Leaderboards:Set(player,"Wins",PlayerData)
		Leaderboards:Set(player,"Kills",PlayerData)
		task.wait(100)
	end
end

function PlayerData:Init()
	for _,player in game.Players:GetPlayers() do
		task.spawn(playerAdded,player)
	end
	
	game.Players.PlayerAdded:Connect(playerAdded)
	game.Players.PlayerRemoving:Connect(function(player)
		--Leaderboards:Set(player,"Wins",PlayerData)
		--Leaderboards:Set(player,"Kills",PlayerData)
		if Profiles[player] then
			Profiles[player]:Release()
		end
	end)
	Bindables.OnServer.Event:Connect(function(signal,player)
		if signal == "Undo" then
			ProfileStore:LoadProfileAsync("Player_"..player.UserId)
		end
	end)
	task.spawn(function()
		while true do
			Leaderboards:Refresh("Kills")
			Leaderboards:Refresh("Wins")
			task.wait(100)
		end
	end)
end

local function getProfile(player)
	assert(Profiles[player],string.format("Profile does not exist for %s",player.UserId))
	
	return Profiles[player]
end

function PlayerData:Get(player,key)
	local profile = getProfile(player)
	assert(profile.Data[key],string.format("Data does not exist for key: %s", key))
	
	return profile.Data[key]
end

function PlayerData:Set(player,key,value)
	local profile = getProfile(player)
	assert(profile.Data[key],string.format("Data does not exist for key: %s", key))
	assert(type(profile.Data[key]) == type(value))
	
	profile.Data[key] = value
end

function PlayerData:Update(player,key,callback)
	local profile = getProfile(player)
	local oldData = self:Get(player,key)
	local newData = callback(oldData)
	self:Set(player,key,newData)
end

return PlayerData

In the script there is a bindable event I made to undo the issue I’m currently having. I also used a bindable event which caused this problem, which used ProfileStore:WipeProfileAsync to eliminate my player’s profile.

When I also print the profile that is loaded when the player is added, it actually prints the profile even though it says a profile cannot be found. Profiles[player] is nil though.

Point of error in code is an assert:

assert(Profiles[player],string.format("Profile does not exist for %s",player.UserId))

I tried redoing my PlayerData module in another game and putting it in here but I got the same error.

local Bindables = game.ReplicatedStorage.Bindables
local Players = game:GetService("Players")

local ProfileService = require(script.ProfileService)
local Leaderstats = require(script.Leaderstats)
local Leaderboards = require(script.Leaderboards)

local ProfileStore = ProfileService.GetProfileStore(
    "PlayerProfile",
    dataTemplate
)

local Profiles = {}

local function playerAdded(player)
    local profile = ProfileStore:LoadProfileAsync("Player_"..player.UserId)
    if profile then
        profile:AddUserId(player.UserId)
        profile:Reconcile()

        profile:ListenToRelease(function()
            Profiles[player] = nil
            player:Kick()
        end)

        if not player:IsDescendantOf(Players) then
            profile:Release()
        else
            Profiles[player] = profile
            Leaderstats:Init(player, profile, PlayerData)
        end
    else
        player:Kick()
    end
end

function PlayerData:Init()
    for _, player in ipairs(game.Players:GetPlayers()) do
        task.spawn(playerAdded, player)
    end

    game.Players.PlayerAdded:Connect(playerAdded)

    game.Players.PlayerRemoving:Connect(function(player)
        if Profiles[player] then
            Profiles[player]:Release()
        end
    end)

    Bindables.OnServer.Event:Connect(function(signal, player)
        if signal == "Undo" then
            -- Reload the profile if "Undo" signal is received
            local profile = ProfileStore:LoadProfileAsync("Player_"..player.UserId)
            if profile then
                Profiles[player] = profile
                Leaderstats:Init(player, profile, PlayerData)
            end
        end
    end)

    task.spawn(function()
        while true do
            Leaderboards:Refresh("Kills")
            Leaderboards:Refresh("Wins")
            task.wait(100)
        end
    end)
end

local function getProfile(player)
    assert(Profiles[player], string.format("Profile does not exist for %s", player.UserId))
    return Profiles[player]
end

function PlayerData:Get(player, key)
    local profile = getProfile(player)
    assert(profile.Data[key], string.format("Data does not exist for key: %s", key))
    return profile.Data[key]
end

function PlayerData:Set(player, key, value)
    local profile = getProfile(player)
    assert(profile.Data[key], string.format("Data does not exist for key: %s", key))
    assert(type(profile.Data[key]) == type(value))
    profile.Data[key] = value
end

function PlayerData:Update(player, key, callback)
    local profile = getProfile(player)
    local oldData = self:Get(player, key)
    local newData = callback(oldData)
    self:Set(player, key, newData)
end

return PlayerData

You need to wait for the Profile to exist because :LoadProfileAsync is a yielding function

Replace:

With:

local function getProfileAsync(player,timeout?)
    local timeout = timeout or 15
    local t = 0
    repeat
          t += game:GetService("RunService").Hearbeat:Wait()
    until Profiles[player] or t >= timeout

    assert(Profiles[player],"Profile for ".. player.Name.." took too long to load")
	return Profiles[player]
end

I thought the PlayerAdded events werent timing right. I just stopped using profileservice but I’ll keep that in mind if I ever use profileservice in my game again because I think it would work.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.