For some reason, UserOwnsGamepassAsync does not return
true even after I purchased the gamepass.
MarketplaceService.PromptGamePassPurchaseFinished:Connect(function (player, gamePassID, wasPurchased)
if wasPurchased then
print(MarketplaceService:UserOwnsGamePassAsync(player.userId, gamePassID)) --> false
UserOwnsGamePassAsync caches, and roughly resets every 10 seconds, hence the problem you’re facing (see this). You shouldn’t need to check UserOwnsGamePassAsync inside PromptGamePassPurchaseFinished, but rather check the wasPurchased argument.
Note: This does not work vice versa, UserOwnsGamePassAsync will always return true if they purchase it in game (or own it upon joining), until they leave.