ExperienceNotificationService:CanPromptOptInAsync() not working (again)


We’ve received some errors in a game
The player cannot be prompted. Please check ExperienceNotificationService:CanPromptOptIn first before calling ExperienceNotificationService:PromptOptIn

The code involved in a LocalScript is

	if not Players.LocalPlayer:GetAttribute("promptOptIn") then
		local ExperienceNotificationService = game:GetService("ExperienceNotificationService")
		pcall(function()
			if ExperienceNotificationService:CanPromptOptInAsync() then
				ExperienceNotificationService:PromptOptIn()
			end
		end)
		Players.LocalPlayer:SetAttribute("promptOptIn", true)
	end

I believe we should be using the api correctly.

I think this should be

if not Players.LocalPlayer:GetAttribute("promptOptIn") then
    local ExperienceNotificationService = game:GetService("ExperienceNotificationService")
    pcall(function()
        if ExperienceNotificationService:CanPromptOptInAsync() then
            ExperienceNotificationService:PromptOptIn()
        end
    end)
    Players.LocalPlayer:SetAttribute("promptOptIn", true)
end
1 Like

thanks for reply but I am afraid I don’t seem to find a difference between the code you posted and mine. i’m a bit confused

Hi EtNowis, could you please try script below? It’s updated to consume both apiCallSuccessful and canActuallyPrompt following the code examples here

if not Players.LocalPlayer:GetAttribute("promptOptIn") then
	local ExperienceNotificationService = game:GetService("ExperienceNotificationService")
	pcall(function()
        -- Capture both return values
		local apiCallSuccessful, canActuallyPrompt = ExperienceNotificationService:CanPromptOptInAsync()
        -- Check both conditions explicitly
		if apiCallSuccessful and canActuallyPrompt then
			ExperienceNotificationService:PromptOptIn()
		end
	end)
	Players.LocalPlayer:SetAttribute("promptOptIn", true)
end
1 Like

thanks for the reply. i guess this is the way and the document need to update.

it states the return is a single boolean whether the player can be prompted. but from the example code, it should actually be

boolean whether the call is successful
boolean whether the player can be prompted 

This is the same for most API calls as there is always a chance that the HTTP request fails. However, not all the documentation for functions that request to the roblox API explicitly state that using a pcall is required (although it is recommended)

no it is not the case.
other api with single output of boolean like Player:IsInGroup() also return the correct single boolean. not two.

when a method is wrapped with pcall() it prepend the additional boolean indicating whether the pcall itself is successful or not. and then the rest of them are the returns from the original functions

read the difference between the following codes:

-- unprotected, but inGroup would be true/false and it is the status of player
local inGroup = player:IsInGroup()
-- protected, notice we get the returns outside the pcall
-- useful when we want to know if the pcall failed
local success, inGroup = pcall(function()
    return player:IsInGroup()
end)
-- protected, but we don't care if the call failed
pcall(function()
    local inGroup = player:IsInGroup() -- we don't have 'two boolean' here
end)

Hi EtNowis, you have a point here about pcall() - my suggestion above might be incorrect as CanPromptOptInAsync does only return one boolean value.

Would you mind sharing your universe id so that I can take a deeper look?

1 Like

Hey EtNowis, following up after looking into the logs for your universe.

I’ve noticed a pattern that the script seemed to be executed multiple times in parallel, in order of time:
T0: 1st request: CanPromptOptIn succeeded
T1: 2nd request: CanPromptOptIn succeeded
T2: 1st request: PromptOptIn succeeded
T3: 2nd request: PromptOptIn failed (because the user has already been successfully prompted in 1st request)

To confirm above theory, could you please try something like below to prevent multiple parallel calls to prompt?

	if not Players.LocalPlayer:GetAttribute("promptOptIn") then
        Players.LocalPlayer:SetAttribute("promptOptIn", true) -- moved to here to prevent parallel calls 
		local ExperienceNotificationService = game:GetService("ExperienceNotificationService")
		pcall(function()
			if ExperienceNotificationService:CanPromptOptInAsync() then
				ExperienceNotificationService:PromptOptIn()
			end
		end)
	end
1 Like

OH! that’s indeed an overlook by us, we forget it is async.
Good to know the api is consistent
I’ll try it out tonight (12 hrs from now).

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