Nothing in the thread yet, so worth saying first: the reason this is hard to debug is that your pcall cannot see the failure you are looking at.
Check the signature. SocialService:PromptFeedbackSubmissionAsync(options: Dictionary?) takes no player parameter. It prompts whoever’s client it runs on, which tells you two things: it is a client call, and the “limit reached” screen you screenshotted is drawn by the CoreScripts rather than returned to you.
Look at what SocialService exposes around it:
ShowPromptFeedbackSubmission (Event, RobloxScriptSecurity)
ShowPromptFeedbackUnavailable (Event, RobloxScriptSecurity)
SignalFeedbackSubmissionCompleted (Function, RobloxScriptSecurity)
SignalFeedbackSubmissionPermissionDenied (Function, RobloxScriptSecurity)
You cannot call or connect to any of those. They are the CoreScript’s half of the conversation. Reading the surface, your call raises the Show event, the CoreGui decides whether to draw the form or the unavailable screen, and completion or permission-denied is signalled back through the engine, not back through your thread. So _success comes back true, your warn never fires, and the only thing that has ever told you something is wrong is a screenshot. That matches what you are describing.
Two concrete things to change.
Pass the options table. You are calling it bare:
social_service:PromptFeedbackSubmissionAsync( )
Enum.FeedbackType has exactly two values, Feedback and PlayerSupport, and the documented example passes one explicitly:
social_service:PromptFeedbackSubmissionAsync( { FeedbackType = Enum.FeedbackType.PlayerSupport } )
Try both before assuming the API is broken. They are two different flows and right now you are not choosing either one.
Confirm which side this is running on. ProximityPromptService.PromptTriggered fires on the server as well as on the client, so this handler looks alive in both places. If it is in a Script, the call has no client to target and _player is doing nothing for you. One line will tell you:
print( "feedback handler on client:", game:GetService( "RunService" ):IsClient( ) )
If that prints false, move the handler into a LocalScript and gate it on the local player:
local players = game:GetService( "Players" )
proximity_prompt_service.PromptTriggered:Connect( function( _prompt, _player )
if ( _player ~= players.LocalPlayer ) then return end
if ( not collection_service:HasTag( _prompt, TAG_NAME ) ) then return end
local _success, _error = pcall( function( )
social_service:PromptFeedbackSubmissionAsync( { FeedbackType = Enum.FeedbackType.PlayerSupport } )
end )
if ( not _success ) then
warn( "Failed to open feedback dialog:", _error )
end
end )
Last thing, and I would test this one early because it is cheap. You mention the place is restricted to group members. There is a distinct SignalFeedbackSubmissionPermissionDenied path in that API, separate from any limit. The same “you have reached your feedback limit” screen appearing for every player, including accounts that have never submitted feedback once, reads a lot more like a blanket unavailable or denied state than like a per-user counter that maxed out for everyone at the same time. Flip a test build to public for five minutes and see whether the prompt behaves differently. If it does, this is an access problem and not a limit.