[Live] Changes to Game Passes

Asynchronous calls always need to be wrapped in pcall. They can fail for connectivity issues or the service being down. You need to be able to handle these spontaneous errors.

5 Likes

Note taken, thanks! :slightly_smiling_face:

I’ve been having this exact issue sparadically and it sounds unreal to me. My game reaches very high traffic so it’s a hotbed for this issue and I’ve been dealing with lots of complaints. I can’t find any pattern why this happens so I’m assuming it’s random? By chance, are you still dealing with this issue?

Exclusively on weekends for me. It’s incredibly annoying.

I’d say 1 out of 500 purchases have this happen as an educated guess

Now this error message should contain invalid data which might explain why it fails. Could you please send it to me if you meet one? Thanks.

Load passes fail:MarketPlace::UserOwnsGamePassAsync: Parsed invalid JSON: ï»ż{"errors":[{"code":0,"message":"Something went wrong with the request, see response status code."}

Load passes fail:MarketPlace::UserOwnsGamePassAsync: failed due to empty response

So I’m pretty heated now.
Can we talk about how in these release notes just released here: https://wiki.roblox.com/index.php?title=ReleaseNotes/350

It says this:

The result of MarketplaceService:UserOwnsGamePassAsync will now be cached.

This was the one thing that EVERYONE was complaining about and was asking about when this new service was released. Why is it now going to cache again? This is a huge pain point because we have to implement a separate check every time we sell something in-game again if they bought it in the game. Also, if they buy it from the store page while in-game, we have no way to know that they now have the gamepass unless they rejoin the server!

Am I misunderstanding something? Why this change when we were assured this new service wouldn’t cache (and it didn’t up until now)?

7 Likes
1 Like

My original post was slightly inaccurate, and I apologize for any confusion.
I have investigated further into how it works, and here is what I’ve currently observed:

  • If the user owns the gamepass upon the initial check, it will remain true for the full game session.
  • If the user does not own the gamepass, it will cache that false result for about 10 seconds before allowing a live result to be returned again.

So yes, there is now a slight discrepancy, but what’s important to note here is that it won’t stay false if you call it when the user doesn’t own the gamepass. If you check again shortly after, it will give you a live result again.

4 Likes

What happens if the user buys the gamepass in-game within that 10 seconds? Will the cached value for that gamepass be cleared?

1 Like

You would use PromptGamePassPurchaseFinished/etc to detect when the player purchases a gamepass in-game – not constantly polling UserOwnsGamePassAsync.

Seems this is more relevant to purchasing gamepasses outside the game (store page), and I doubt that would clear the cache. Roblox would constantly have to poll the webserver to check if the player bought the pass to know when to invalidate the cache, defeating the purpose of caching the value for 10 seconds.

2 Likes

I understand that it makes sense to use PromptGamePassPurchaseFinished to give gamepass rewards ASAP, but in some cases UserOwnsGamePassAsync is checked on button press, on touch, or through event-triggered scenarios. Just because UserOwnsGamePassAsync is run after a gamepass is purchased in-game does not mean that it’s being polled constantly.

In these cases it would be nice for Roblox to automatically clear the cache for a bought gamepass when it’s purchased in-game. There is no reason to have to wait 10 seconds for the cache to update when the Roblox server has already knows that the cache is no longer valid.

If Roblox doesn’t implement this, then the only way to have event-triggered passes work within that 10 second window is if we write our own cache on top of Roblox’s cache that updates when users purchase passes. This should not be necessary. The Roblox gamepass system and its caching mechanism should be good enough to support this use case.

Some examples of event-triggered passes:

  • A door that only lets you through if you own a gamepass
  • A button that teleports you. If you own the gamepass, you teleport. If you don’t own the gamepass, it prompts you to purchase it.
  • Special abilities for gamepass owners in a round-based game, which is checked only at the start of the round.

I could list other examples, but I don’t think I need to. In all three of these examples, having to wait 10 seconds after purchasing a gamepass is an annoyance. This is an even greater annoyance in the round-based game scenario, since users will have to wait the whole round to use their gamepass.

This issue can be worked around, but we shouldn’t have to work around it. Roblox already has a cache. We shouldn’t have to write our own with a small bit of extra behavior just because Roblox’s isn’t good enough. If Roblox is aiming to make checking and handling gamepasses easy for developers and responsive for players, then for event-triggered scenarios we need the gamepass cache to clear for passes that are bought in-game.

8 Likes

What I personally do is set a module with a UserOwnsGamepass function. This module has an internal purchase cache of all gamepass purchases made in that particular server and will check against this cache before calling UserOwnsGamePassAsync.

3 Likes

Do not necrobump old announcements