"Attempt to call a boolean value" in ProcessReceipt function

I am trying to achieve a working ProcessReceipt function, the issue with this is that it keeps throwing the error Attempt to call a boolean value and I can’t find out why or where it does that, the script it throws that error is this function right here:

productFunctions[0] = function(Player)
	local PlayerData = ServerStorage.PlayerData:FindFirstChild(Player.Name)
	local ProductId = 0
	local GamepassFolder = PlayerData:WaitForChild("Gamepasses",60)
	if GamepassFolder then
		if not GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			local Success,ErrorMessage = pcall(function()
				local HasData = GamepassDatastore:GetAsync(Player.UserId)
				if HasData then
					GamepassDatastore:UpdateAsync(Player.UserId,function(OldValue)
						local NewValue = {}
						NewValue[#OldValue+1] = ProductId
						return NewValue
					end)
				elseif not HasData then
					local NewData = {ProductId}
					GamepassDatastore:SetAsync(Player.UserId,NewData)
				end
			end)
			if Success then
				local NewValue = Instance.new("NumberValue",GamepassFolder)
				NewValue.Name = MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name
				return true
			elseif not Success then
				warn("Error: "..ErrorMessage)
				return false
			end
		elseif GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			return false
		end
	elseif not GamepassFolder then
		return false
	end
end

Any help is appreciated.

Are you sure you’re not getting any line numbers?

This is all what prints out

If needed, this is the entire module:

local module = {}

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")

local GamepassDatastore = DataStoreService:GetDataStore("GamepassDatastore")

local productFunctions = {}

productFunctions[0] = function(Player)
	local PlayerData = ServerStorage.PlayerData:FindFirstChild(Player.Name)
	local ProductId = 0
	local GamepassFolder = PlayerData:WaitForChild("Gamepasses",60)
	if GamepassFolder then
		if not GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			local Success,ErrorMessage = pcall(function()
				local HasData = GamepassDatastore:GetAsync(Player.UserId)
				if HasData then
					GamepassDatastore:UpdateAsync(Player.UserId,function(OldValue)
						local NewValue = {}
						NewValue[#OldValue+1] = ProductId
						return NewValue
					end)
				elseif not HasData then
					local NewData = {ProductId}
					GamepassDatastore:SetAsync(Player.UserId,NewData)
				end
			end)
			if Success then
				local NewValue = Instance.new("NumberValue",GamepassFolder)
				NewValue.Name = MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name
				return true
			elseif not Success then
				warn("Error: "..ErrorMessage)
				return false
			end
		elseif GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			return false
		end
	elseif not GamepassFolder then
		return false
	end
end

function module.ProcessReceipt(ReceiptInfo)
	local Player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
	local ProductId = ReceiptInfo.ProductId
	if not Player then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	local ProductHandler = productFunctions[ProductId](Player)
	local Success,Result = pcall(ProductHandler)
	if not Success or not Result then
		warn("There was an error processing the product '".. MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name.."' for the player ".. Player.Name..".")
		print("Result: "..Result)
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

return module

And this is the way i am calling this module:

local MarketplaceService = game:GetService("MarketplaceService")
local ProductModule = require(script.ProductModule)

MarketplaceService.ProcessReceipt = ProductModule.ProcessReceipt

This might cause a problem down the road since you are deleting OldValue’s data. Make sure you keep the data from OldValue.

As for the main problem, comment out the pcall because pcall will suppress the line number. It will be a lot more convenient if I can see the line number the problem occurs on.

1 Like

Yeah, please comment the pcall - we can’t see the line number.

The problem seems to be on lines 54 and 55. If I’m right, changing lines 54 and 55 to this will fix the issue.

	local ProductHandler = productFunctions[ProductId]
	local Success,Result = pcall(ProductHandler, Player)

Original:

	local ProductHandler = productFunctions[ProductId](Player)
	local Success,Result = pcall(ProductHandler)

Comment in like putting:

-- Comment

To a pcall or something else?

The issue is still there after changing it to that

Edit:

Turns out that after removing parts from the function that this might be one causing the problem:

productFunctions[0] = function(Player)
	local PlayerData = ServerStorage.PlayerData:FindFirstChild(Player.Name)
	local ProductId = 0
	local GamepassFolder = PlayerData:WaitForChild("Gamepasses",60)
	if GamepassFolder then
		if not GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			local Success,ErrorMessage = pcall(function()
				local HasData = GamepassDatastore:GetAsync(Player.UserId)
				GamepassDatastore:UpdateAsync(Player.UserId,function(OldValue)
					local NewValue = {}
					for Index,Value in ipairs(OldValue) do
						NewValue[#NewValue+1] = Value
					end
					NewValue[#NewValue+1] = ProductId
					return NewValue
				end)
			end)
			return true -- < This might be the one causing the problem.
		end
	end
end

Is the return true removed will it print “Attempt to call a nil value” is it kept will it print already said error.

Can you show me the full script after you add in the change I made? That was exactly the problem I tried to fix.

I did add the player argument into the pcall but i had to keep the (Player) as the function needs the player argument

local module = {}

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")

local GamepassDatastore = DataStoreService:GetDataStore("GamepassDatastore")

local productFunctions = {}

-- // Own Avatar [Gamepass]
productFunctions[0] = function(Player)
	local PlayerData = ServerStorage.PlayerData:FindFirstChild(Player.Name)
	local ProductId = 0
	local GamepassFolder = PlayerData:WaitForChild("Gamepasses",60)
	if GamepassFolder then
		if not GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			local Success,ErrorMessage = pcall(function()
				local HasData = GamepassDatastore:GetAsync(Player.UserId)
				GamepassDatastore:UpdateAsync(Player.UserId,function(OldValue)
					local NewValue = {}
					for Index,Value in ipairs(OldValue) do
						NewValue[#NewValue+1] = Value
					end
					NewValue[#NewValue+1] = ProductId
					return NewValue
				end)
			end)
			return true -- < This is the trouble maker
		end
	end
end

function module.ProcessReceipt(ReceiptInfo)
	local Player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
	local ProductId = ReceiptInfo.ProductId
	if not Player then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	local ProductHandler = productFunctions[ProductId](Player)
	local Success,Result = pcall(ProductHandler, Player)
	if not Success or not Result then
		warn("There was an error processing the product '".. MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name.."' for the player ".. Player.Name..".")
		print("Result: "..Result)
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

return module

That’s the problem. Adding it to the pcall will take care of that automatically. Here is the flow as I am seeing it.

productFunctions is the table of functions
productFunctions[ProductId] is the function specific to that product
productFunctions[ProductId](Player) calls the function with the player argument, turning the whole thing into a bool value.

Remove the player and the parentheses from line 54.

Update with a little more info. pcall calls a function in a protected environment.
pcall(functionToCall [, arg1 [, arg2 [, ...]]])
In this case, we are calling ProductHandler where arg1 is Player.

Now it is printing “Attempt to call a nil value”

local module = {}

local Players = game:GetService("Players")
local MarketplaceService = game:GetService("MarketplaceService")
local ServerStorage = game:GetService("ServerStorage")
local DataStoreService = game:GetService("DataStoreService")

local GamepassDatastore = DataStoreService:GetDataStore("GamepassDatastore")

local productFunctions = {}

-- // Own Avatar [Gamepass]
productFunctions[0] = function(Player)
	local PlayerData = ServerStorage.PlayerData:FindFirstChild(Player.Name)
	local ProductId = 0
	local GamepassFolder = PlayerData:WaitForChild("Gamepasses",60)
	if GamepassFolder then
		if not GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			local Success,ErrorMessage = pcall(function()
				local HasData = GamepassDatastore:GetAsync(Player.UserId)
				GamepassDatastore:UpdateAsync(Player.UserId,function(OldValue)
					local NewValue = {}
					for Index,Value in ipairs(OldValue) do
						NewValue[#NewValue+1] = Value
					end
					NewValue[#NewValue+1] = ProductId
					return NewValue
				end)
			end)
			if Success then
				local NewValue = Instance.new("NumberValue",GamepassFolder)
				NewValue.Name = MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name
				return true
			elseif not Success then
				warn("Error: "..ErrorMessage)
				return false
			end
		elseif GamepassFolder:FindFirstChild(MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name) then
			return false
		end
	elseif not GamepassFolder then
		return false
	end
end

function module.ProcessReceipt(ReceiptInfo)
	local Player = Players:GetPlayerByUserId(ReceiptInfo.PlayerId)
	local ProductId = ReceiptInfo.ProductId
	if not Player then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	local ProductHandler = productFunctions[ProductId]
	local Success,Result = pcall(ProductHandler,Player)
	if not Success or not Result then
		warn("There was an error processing the product '".. MarketplaceService:GetProductInfo(ProductId,Enum.InfoType.Product).Name.."' for the player ".. Player.Name..".")
		print("Result: "..Result)
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	return Enum.ProductPurchaseDecision.PurchaseGranted
end

return module

Edit:

Nevermind, i’ve forgotten to put the id back into there

1 Like