"UserOwnsGamePassAsync can only query local player" error

Hello! So I recently worked on a Rank Donation Center, I used a tutorial by the way.
I run into trouble when executing this code:

script.Parent.MouseButton1Click:Connect(function()
if game:GetService("MarketPlaceService"):UserOwnsGamePassAsync(7564322, game.Players.LocalPlayer.UserId) then
    local rankid = 5 
    game.ReplicatedStorage.RankPlayer:FireServer(game.Players.LocalPlayer, rankid)
end
end)

So the first time I did it without a end (didn’t work), I put a end (didn’t work).

What should I do?

2 Likes

What error are you receiving?

Also you don’t need to fire the event with the player, since the server knows which client it came from.

UserOwnsGamePassAsync takes the UserId as the first argument and the gamepass id as the second.
Also, it’s MarketplaceService - not MarketPlaceService.

I get this error:

1 Like

@teddyHV11 it looks like you are using the script on a server script

I use, it is a 2 module scripts on a script.

1 Like

You should use a localscript and not a serverscript (a script)

1 Like

I feel the way this is set up is asking for trouble, unless you have additional server checks, but I cannot tell from the code you have posted. Though it looks as though you don’t.

Also, when you fire the RemoteEvent, you pass the player as a parameter. This isn’t necessary as when clients fire a remote, the first argument passed to the connection signal will be the player object that fired the remote. When checking if a user owns a pass, the userId should be the first parameter, and the passId being the second.

As you’ve probably heard before, you should never trust the client. But the way it’s currently working seems to be doing the exact opposite. You want the client to request a rank, and have the server validate whether or not they should get it. So, instead of checking if they own a pass on the client, have the client request a rank and then check if they own the corresponding pass like so:

Server

local ranks = {
--  [rank] = passId;
    [5] = 7564322;
}

local marketServ = game:GetService("MarketplaceService")

game.ReplicatedStorage.RankPlayer.OnServerEvent:Connect(plr, rank)
    local pass = ranks[rank] -- Look up corresponding pass for requested rank
    
    if not pass then -- If pass doesn't exist, stop processing
        return
    end
    
    if marketServ:UserOwnsGamePassAsync(plr.UserId, pass) then
        -- Server ranking logic here
    end
end)

Client

local rank = 5 -- Rank to be requested

script.Parent.MouseButton1Click:Connect(function()
    game.ReplicatedStorage.RankPlayer:FireServer(rank) -- Request the rank
end)

If you were checking on the client for feedback, so you can display a message if they don’t own the pass then you should consider using a RemoteFunction instead. This way, you can return the success of the request. You could also have the validation logic on the client as well as the server, but not just on the client as this would be a large vulnerability - especially for changing user ranks!

2 Likes

Thanks, I’ll test it and see if it works.

game:GetService("MarketPlaceService"):UserOwnsGamePassAsync(7564322, game.Players.LocalPlayer.UserId)

You have your parameters reversed; it should be

game:GetService("MarketplaceService"):UserOwnsGamePassAsync(game.Players.LocalPlayer.UserId,7564322)
2 Likes

check this thread Here

PlayerHasPass is deprecated and should not be used. This function is intended to work with any game passes that still have an id on the catalog id system (migrated passes not created after the update). All game passes are on a separate id system now which UserOwnsGamePassAsync respects.

1 Like