Problem
As a Roblox developer, it is currently impossible to reliably catch warning messages in game. Use of the log service is problematic because the documentation states that it’s not entirely reliable as shown in the screenshot below.
The LUA globals pcall and xpcall do not capture warnings as they return true even if there was a warning.
Use Case 1
The first use case involves the DataStore
service since it can produce both errors and warnings. Such a critical function would need to have both errors and warnings handled. Unfortunately, only errors can be handled since there is no way to reliably determine if an warning occurred. Current code looks something like this:
-- Saves the player's data to the data store.
local function saveData(player, data)
local repeatCount = 0
local retryTime = 1
local previous = { 0, 0 }
local status, message
status = false
while status == false do
status, message = pcall(function()
gameData:SetAsync(player.UserId, data)
end)
if status == false then
local msg = string.format("DataStore:SetAsync() Failure: (%s:%d): %s",
player.Name, player.UserId, message)
warn(msg)
if repeatCount <= 5 then
task.wait(retryTime)
previous[2] = previous[1]
previous[1] = retryTime
retryTime = previous[1] + previous[2]
repeatCount += 1
else
warn("DataStore retry count exceeded, aborting...");
break
end
else
local msg = string.format("Player's data saved: %s:%d", player.Name, player.UserId)
print(msg)
end
end
end)
A similar pattern can be applied to any Roblox API or custom LUA function.
Use Case 2
A second use case would be to capture the warning message and send it to an external logging service by using a web hook for further analysis. Granted, the viability of this is unknown since Roblox has recently deployed tools that allow developers to view errors and warnings on live servers via the Roblox Creator website.
Since Roblox developers are a creative lot, I’m sure that there are other use cases out there that I have not considered.
Proposed Solution
Since pcall()
and xpcall()
exist, a proposed solution would be to add a Roblox global. The name could be something like wpcall()
to follow current naming conventions. It could return false to indicate that there was an error or warning, or true to indicate that it succeeded. Alternatively, there could be a new enumeration such as Enum.WPCallResult
to indicate the return status. The values of such an enumeration could be as follows:
-
Enum.WPCallResult.Success
The function inside the wpcall did not encounter any errors or warnings. -
Enum.WPCallResult.Warning
A warning was raised. -
Enum.WPCallResult.Error
An error was raised.
By using enumerations, a script can differentiate between errors and warnings and take different actions for each. Consider the following code:
local status, result = wpcall(function()
-- Do something that can have an error or warning.
end)
if status == Enum.WPCallResult.Error then
-- Do something about the error.
elseif status == Enum.WPCallResult.Warning then
-- Do something about the warning.
else
-- Proceed Normally.
end)
It is understood that a warning is generally considered not a failure as Roblox APIs will succeed even if a warning is generated. However, this does not always apply to custom LUA functions in scripts that generate both errors and warnings. In such a case, a warning could indicate a partial success or failure that may leave data in an inconsistent state which would necessitate the use of an audit to verify and/or correct the erroneous data. Although this would heavily depend on the skills and coding practices of the developer of said function as it pertains to proper cleanup if a runtime exception is encountered.
Conclusion
If Roblox is able to address this issue, it would improve my development experience because it would close a gaping hole in error handing when warnings occur which will allow robust scripts to handle warnings accordingly. It would also provide a more reliable and robust way of capturing warnings to be analyzed later and have them sent offsite to a logging server via a web hook.