Need help! very weird bug

For some reason users of a game I work on are reporting negative times occurring for research that works offline. I cannot for the life of me figure out why, at first I thought it was something to do with os.time(), because I found this Is os.time synced between client and server - #8 by Tiffblocks
However, the bug is still being reported… HOW CAN THIS BE FIXED?! I really don’t see how this is occuring…

The client invokes this function when the user clicks on a research frame

  DoResearch.OnServerInvoke = function(player, research)
      local Profile = ProfileService:GetProfile(player)
      if Profile.Money >= Research[research].Cost and not Profile.Research[research] then
        local StartTime = workspace:GetServerTimeNow()
        Profile.Research[research] = StartTime
        MainModule:AddMoney(player, -Research[Research].Cost)
        return true
      else
        return false
      end
  end

Then every second the server runs this code (It’s in it’s own while task.wait(1) loop).

for _, player in Players:GetPlayers() do
    local Profile = ProfileService:GetProfile(player)
    local a, b = pcall(function()
	    for research, StartTime in Profile.Research do
	           local TotalTime = Research[research].Time
	           if workspace:GetServerTimeNow()-StartTime > TotalTime or workspace:GetServerTimeNow()-StartTime < 0 then
                           Profile.Research[research] = nil
                           MainModule:AddMoney(player, Research[research].Gain)
                  end
         end
    end)
    if b then
       warn(b, " long research updater", Profile.IsLoaded) -- Error analytics only shows 26 of this warning but more than 26 users have reported it. + it would fire multiple times if it were a constant issue.
    end
end

To display the remaining time client runs this every second.

local function toHMS(s)
    return string.format("%02i:%02i:%02i", s/60^2, s/60%60, s%60)
end
function module:UpdateTimer() -- called every second from another script
  local Research = ReplicatedStorage.Functions.GetProfileData:InvokeServer("Research")
  for _, Frame: Frame in script.Parent.Research.Main:GetChildren() do -- Where the research frames are held.
        if not Frame:IsA("Frame") then continue end
	local StartTime = Research[Frame.Name]
	if not StartTime then
	    Frame.WaitTime.Visible = false
            continue
	elseif workspace:GetServerTimeNow()-StartTime < 0 then
	    warn("Send in feedback this error code: ErrorCode 15 (123)", workspace:GetServerTimeNow(), StartTime, Research[Frame.Name].Time, Frame.Name)
	elseif floor( ClientModule[Frame.Name].Time - (workspace:GetServerTimeNow()-StartTime)) < 0 then
            -- This code keeps being shown in error analytics but HOW??!?!
	    warn("Send in feedback this error code: ErrorCode 16 (125)", workspace:GetServerTimeNow(), StartTime, Research[Frame.Name].Time, Frame.Name)
	end
	
	Frame.WaitTime.Visible = true
	Frame.WaitTime.Text = toHMS(math.floor( Research[Frame.Name].Time - (workspace:GetServerTimeNow()-StartTime)))
    end
end

Do you know how big of a negative number it is? If the number is very small, like -0.1, then it’s likely caused by the player having variable network lag. Like if the clock was setup assuming they have 300ms ping, then their ping later drops to 150ms, then the clock will be out of sync by 150ms. This means that a value of “now” sent from the server to the client would be 150ms further in the past than expected, which could result in a negative number.

If the number is much larger than that, like -100, or even something like -1717457288, then it could point to a bug somewhere else in your code.

My suggestion would be to make your code resilient to network issues like this by clamping the number to zero so that it’s never negative.

1 Like

It can be like -100 hours sometimes, just random.

I guess I could create a temporary event that the client fires to the server and the server runs a check and returns the remaining time…

Its a possibility you are having an instance where you are overflowing the max value of the number type in lua.

I am rather certain that the max numerical value that can be held inside of a number type is 2^32 or 32 bits of data including the binary value to represent positive or negative.