Erasing Player Data from ProfileService

  1. What do you want to achieve?
    How can I erase player data from profileservice if there is a data deletion request?

  2. What is the issue?
    How can I do that?

  3. What solutions have you tried so far?
    I looked on Google and found no results.

2 Likes

The API on ProfileService’s GitHub page mentions that the WipeProfileAsync() method allows for this to be possible. Here’s the example that is provided:

ProfileStore:WipeProfileAsync()


ProfileStore:WipeProfileAsync(profile_key) --> is_wipe_successful [bool]
-- profile_key   [string] -- DataStore key

Use :WipeProfileAsync() to erase user data when complying with right of erasure requests. In live Roblox servers :WipeProfileAsync() must be used on profiles created through ProfileStore.Mock after Profile:Release() and it’s known that the Profile will no longer be loaded again.

6 Likes

Hello @StrongBigeMan9, I have the following question regarding wiping data from the ProfileStore. I am working with Profile Service for my game and I don’t want to actually “save” the data, I want to start fresh in the studio to continuously bug test without ProfileStore:WipeDataAsync() holding up my studio for 20 seconds after stopping the playtest every time.

1 Like

From my understanding, utilizing ProfileStore.Mock would enable you to achieve that since ProfileService would work like normal except no DataStore calls would be made. Here are some examples provided by loleris:


ProfileService’s GitHub Example

local ProfileTemplate = {}
local GameProfileStore = ProfileService.GetProfileStore(
  "PlayerData",
  ProfileTemplate
)

local LiveProfile = GameProfileStore:LoadProfileAsync(
  "profile_key",
  "ForceLoad"
)
local MockProfile = GameProfileStore.Mock:LoadProfileAsync(
  "profile_key",
  "ForceLoad"
)
print(LiveProfile ~= MockProfile) --> true

-- When done using mock profile on live servers: (Prevent memory leak)
MockProfile:Release()
GameProfileStore.Mock:WipeProfileAsync("profile_key")
-- You don't really have to wipe mock profiles in studio testing
4 Likes

Thank you for the response @StrongBigeMan9! Do you think simply changing the profile to mock when on studio would work? Example:

-- the code below is places under the player added function ---
    if RunService:IsStudio() then
    		profile = ProfileStore.Mock:LoadProfileAsync(
    			""..plr.UserId,
    			"ForceLoad"
    		)
    	else
    		profile = ProfileStore:LoadProfileAsync(
    			""..plr.UserId,
    			"ForceLoad"
    		)
    	end
2 Likes

Based on the examples loleris provided & how its functionality is described on GitHub, it seems that would be the case:

You may load profiles of the same key from ProfileStore and ProfileStore.Mock in parallel - these will be two different profiles because the regular and mock versions of the same ProfileStore are completely isolated from each other.

Aha, It makes sense but in my example above, I am not stating the live profile if the player isnt in studio I am only stating the mock profile.

Sorry for the repetative messages I should’ve just tested it, Looks like the example I sent above works perfectly!

Hi, im trying to use this function but i dont get what’s “profile_key”, for the moment i putted the user_id as a string for profile_key, but i’m not sure if that’s how it works…

Since I’m unsure of the specific format you’ve used for the profile key, I’ll try to explain it with a snippet of code from ProfileService’s GitHub Tutorial Section as an example.


The “profile_key” is the value that’s used when calling ProfileStore:LoadProfileAsync() to access the profile of a player that joined the game:

local function PlayerAdded(player) -- This is the function that is run when a player joins the game
    local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId) -- This will try to load a profile with the given profile key of "Player_UserIdOfPlayerThatJoinedHere"

--[[
The ("Player_" .. player.UserId) is what the profile key would be.
If your UserId was 2312310, for example, the profile key would be Player_2312310
--]]

This means that when utilizing the ProfileStore:WipeProfileAsync() method, the profile key that was used to load that player’s profile is what would be input into this method:

ProfileStore:WipeProfileAsync("Player_2312310")

Ok, so i wrote this function to delete the data of one player

local function DeleteData()
	wait(1)
	local id = -- id here
	local profile = ProfileStore:LoadProfileAsync(
		"Player_"..id,
		"ForceLoad"
	)
	ProfileStore:WipeProfileAsync("Player_"..id)
	print("DataDeleted")
end
DeleteData()

it prints “DataDeleted”, but after some seconds i start getting these errors on the output

 ServerScriptService.DataManager.ProfileService:913: attempt to index nil with 'ActiveSession'

Transform function error ServerScriptService.DataManager.ProfileService:913: attempt to index nil with 'ActiveSession'

 [ProfileService]: DataStore API error [Store:"Player";Key:"Player_1258231508"] - "Undefined error"

What’s wrong here?

The player’s profile needs to be released before the WipeProfileAsync method is called because from my understanding, that player no longer has a profile and therefore does not have an active session where their data would be loaded.

Oh man, i added the release() before wipeProfile but i keep getting the same errors.

local function DeleteData()
	wait(1)
	local id = -- id here
	local profile = ProfileStore:LoadProfileAsync(
		"Player_"..id,
		"ForceLoad"
	)
    profile:Release()
	ProfileStore:WipeProfileAsync("Player_"..id)
	print("DataDeleted")
end
DeleteData()

I forgot to mention this earlier – if this is being run in Roblox Studio, loading the player’s profile would not be necessary for the profile to be cleared.

Here’s what that function could look like without loading the player’s profile:

local function DeleteData()

	local id = -- UserId here

    local clearProfile = ProfileStore:WipeProfileAsync("Player_"..id)
	print(clearProfile) -- This will return true if the profile was cleared successfully
end

DeleteData()

If this was being run in a live server where that player joined, their profile was loaded, then they clicked a button to request that their data would be deleted, for example, you would need to release their profile prior to calling the WipeProfileAsync method.

If you structured your code in a way that listened for a player’s profile to be released, just like what was shown in the example from ProfileService’s GitHub page, then the cached profile would be set to nil and the player should be immediately kicked after their profile was released, meaning that those ActiveSession errors that appeared in relation to their profile shouldn’t affect anything, if I understand correctly.

Example ListenToRelease usage from ProfileService’s GitHub

local function PlayerAdded(player)
    local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId)
    if profile ~= nil then
        profile:AddUserId(player.UserId)
        profile:Reconcile()
        profile:ListenToRelease(function() -- When the profile is released...
            Profiles[player] = nil -- The profile that was cached for this session will be set to nil

            player:Kick() -- The player will be kicked from the session
        end)

    -- Code continues...
2 Likes

It worked! Srry for the late response, ty for helping me.

3 Likes

Late reply, but for anyone that wants a easier way just download this plugin that I made Here Put in there user id and it will show there username and a picture of there profile, then just click Delete Data.

2 Likes

I tried using your plugin today, and it said there were no errors, but this error was thrown at me, and no data was wiped.
BindToClose can only be called on the server. - Edit - ProfileService:369

I made a similar function to the one you listed, and I got this error:

I ran this code in the command prompt:
```local ps = require(game.ServerScriptService.profileService.PlayerDataHandler); ps.DeleteData(292835306)``

Since DeleteData was defined as a method of PlayerDataHandler, the code that was run in the command bar would need to be updated from ps.DeleteData to ps:DeleteData.


The first argument of a Method is always expected to be the object that it’s being called on (which is the PlayerDataHandler, in this case). When calling the function with a colon :, it automatically sends that object through as self, but by calling the function with a dot ., it replaced self with the number you sent through instead of making it the PlayerDataHandler. Consequently, the id parameter was no longer referencing anything, resulting in the error of attempt to concatenate string with nil.

(If you’d like to test this yourself, you could add print(self) to the function and then call the function with something such as ps.DeleteData(1); it would print out 1 instead of the contents of the PlayerDataHandler table).


Useful resource to learn more:

Functions Guide (Methods section) - Roblox Creator Documentation site

Yeah, it was a big mistype on my part. A simple one at that too. I had already tried one or two other methods beforehand that didn’t work, so I did not spend as much time trying to double-check/proof read what I coded before trying something else.

1 Like