UserHasBadgeAsync "Internal Error"

  1. What do you want to achieve? Keep it simple and clear!
    I want to achieve a system where a script checks if a user has a badge and updates GUI text to show whether the badge has been achieved or not.

  2. What is the issue? Include screenshots / videos if possible!
    The issue is that my output log is being flooded with “UserHasBadgeAsync: Internal error.” and I don’t understand why. Here is a screenshot of the output:
    Screenshot 2025-06-10 155100

  3. What solutions have you tried so far? Did you look for solutions on the Creator Hub?
    I have looked at other posts in the Dev Forum to see if anyone else has had a similar problem but I have not found anyone with the same error as me.

Here is my script, I’m not very good at scripting so I assume it’s a problem with the script:

local runService = game:GetService("RunService")
local badgeService = game:GetService("BadgeService")
local player = game.Players.LocalPlayer
local achText = script.Parent.achievedtext

runService.RenderStepped:Connect(function()
	wait(5)
	if badgeService:UserHasBadgeAsync(player.UserId,688285968841371) then
		achText.Text = "[Achieved]"
		achText.TextColor3 = Color3.fromRGB(0, 255, 0)
		script.Enabled = false
	else
		achText.Text = "[Not Achieved]"
		achText.TextColor3 = Color3.fromRGB(0, 0, 0)
	end
end)

wrap it inside pcall
that simple
It heppens very often with Async function like that

local runService = game:GetService("RunService")
local badgeService = game:GetService("BadgeService")
local player = game.Players.LocalPlayer
local achText = script.Parent.achievedtext

local badgeService_UserHasBadgeAsync = badgeService.UserHasBadgeAsync

local try,ret = pcall(badgeService_UserHasBadgeAsync,badgeService,player.UserId,688285968841371)
while not try do
try,ret = pcall(badgeService_UserHasBadgeAsync,badgeService,player.UserId,688285968841371)
end


if ret then
		achText.Text = "[Achieved]"
		achText.TextColor3 = Color3.fromRGB(0, 255, 0)
		script.Enabled = false
	else
		achText.Text = "[Not Achieved]"
		achText.TextColor3 = Color3.fromRGB(0, 0, 0)
	end


I can’t quite tell what exactly the issue could be that it prints an internal error, but personally you wouldn’t need RunService to keep checking for the badge ownership.

Instead, you could have the script check for badge ownership whenever a player opens the menu.

And like Yarik said, putting it into a pcall()-function can make things a bit easier too. You can find an example in the Documentation.

i believe you’re reaching the limit of UserHasBadgeAsync() as you attempt to use it every frame
this is not a while loop, and so that wait(5) wont stop the same function from running on the next frame

you should make a function that checks for badge ownership and retries incase it fails, and if it succeeds, cache the value

you also shouldnt update the ui every frame as its unnecessary and can be achieved without doing that

i do assume that your script is a local script located in a gui, the script i provided below would be best fit for a module script that you could use from anywhere, re-pasting the function in every script would defeat it’s purpose

if you want to, you should learn about module scripts

local BadgeService = game:GetService("BadgeService")
local Players = game:GetService("Players")

local cached = {}
local function hasBadge(player:Player, id:number)	
	if not cached[player] then
		-- if no cache data for the player exists, make a new table
		cached[player] = {}
		
		-- when the player leaves, remove the table to free up memory
		player.AncestryChanged:Once(function()
			cached[player] = nil
		end)
	elseif cached[player][id] ~= nil then -- we check if it's not equal to nil, which means its not cached, if the player owns the badge, it would be true, otherwise it'd be false
		return cached[player][id] -- we already know this badge is owned by this player
	end
	
	local success, res
	local attempts = 0
	
	while not success do -- use a while loop to keep on trying
		success, res = pcall(function() -- wrap function in pcall, so incase it errors the script doesnt stop running
			return BadgeService:UserHasBadgeAsync(player.UserId, id)
		end)
		
		-- if the function succeeded, save the result to cache and return it
		if success then
			cached[player][id] = res
			return res
		end
		
		attempts += 1
		if attempts >= 5 then -- if we tried 5 times and we still have no result, the roblox servers could be lagging, return false
			return false
		end
		
		task.wait(.1) -- wait a tiny bit after retrying
	end
end

-- the first time we do this, it should take longer than the second
print(hasBadge(Players.LocalPlayer, 12345))

if hasBadge(Players.LocalPlayer, 12345) then
	-- change your ui here
end

if you got any questions then i’d be happy to answer!

This seemed to fix the error, but now after I get the badge it doesn’t update the text and says I haven’t achieved it.

Wow roblox just deleted my reply for “off topic” :skull:

Basically make ingame event that upon player reciving badge it would update the title

Sorry I don’t really know how to do that, I tried making a Bindable Event that fires to the script to update the badge upon opening the achievements screen but it just doesn’t work. (Probably cause I don’t really understand pcalls all that well)

“Internal Error”. Hint is in the name. Most likely caused by a slight outage or connection problem but if it continues for other people then it’s a scripting issue

Make event that fires to all clients if player recives the badge

And update the title on a client obviously

Scratch what I said. I think you can’t award a player via the local script so set up a remote event going from the client to a server script with the userid and do it from there (Edit: Wrong, refer back to what I said last time)

Isn’t FireAllClients a remote event thing only? I am using a bindable event because opening the badge screen is local as well but idk.

The problem isn’t awarding the script, just checking if the player has the script. The badge is already awarded in a completely different place, from a regular script.

You need to tell clients to update titles somehow.

It should work but it doesn’t. Have you restarted Roblox Studio and/or testing in the game itself? If you’ve tried that and had the same issue then refer it to Bug Reports since this is unintended behaviour

Im pretty sure my problem there is something to do with the pcall that I am not handling correctly because the event is being recieved but the script is not updating the text. Here is the code I updated:

updateAchievementsEvent.Event:Connect(function()
	if ret then
		achText.Text = "[Achieved]"
		achText.TextColor3 = Color3.fromRGB(0, 255, 0)
		script.Enabled = false
	else
		achText.Text = "[Not Achieved]"
		achText.TextColor3 = Color3.fromRGB(0, 0, 0)
	end
end)

I have restarted studio and testing but it has happened regardless.

What is ret? If ret is UserHasBadgeAsync then it might be the internal error again

Just do:

achText.Text = "[Achieved]"
		achText.TextColor3 = Color3.fromRGB(0, 255, 0)
		script.Enabled = false

No need checking the variable

I changed the code to be like that, but now it just shows I have it achieved even though I don’t have the badge in my inventory.

I assume it is the return from the pcall the other guy wrote in.