Player object stays in game several seconds after player left

I’ve recently been having an issue in my game where the server tries to spawn players that have left (and for a while). I can wrap all the character spawn functions in Pcalls, but the problem is that any script that is currently running through the player continues to run until the game finally removes the player object. That then results in whatever script running in erroring.
I can’t wrap everything in Pcalls to fix the issue, since any script that handles the player object could error half way through.

Checking if the player left doesn’t work either because the script will initially run because the Player object is still in the game.

player left

Approximately ~10 seconds before this warning popped up, the player had left the game, but the game continued to run scripts editing the player and attempting to create a new character. Half way through the character spawn function, the script errored since PlayerGui doesn’t exist on a non-existent Player object.

Is this a lag, Roblox or scripting problem? I haven’t been able to find any information about the warning. I only started seeing this occur about a week ago.

When a player disconnects, Roblox doesn’t instantly remove the player object from the server. There’s a brief delay where the player object remains in the game even though the player has disconnected. This can cause issues if your scripts are still trying to perform actions on the player or its character during this period.

As you’ve discovered, wrapping everything in pcall or checking if the player has left isn’t a perfect solution, because the player object can still be in the game even though the player has actually left, and scripts might start executing before the player disconnects but finish afterwards, leading to errors.

Here’s a potential solution:

When a player leaves the game, Roblox fires the PlayerRemoving event. You can use this event to set a flag indicating that the player is in the process of disconnecting, and then check this flag before performing any operations on the player or its character.

Here’s an example of how you could implement this:

local disconnectingPlayers = {}

game.Players.PlayerRemoving:Connect(function(player)
    disconnectingPlayers[player.UserId] = true
end)

-- Then, before performing operations on a player or its character:

local function performOperation(player)
    if disconnectingPlayers[player.UserId] then
        -- Player is disconnecting, abort operation
        return
    end

    -- Perform operation
end

This won’t completely prevent all conditions, since there’s a brief period between when the player disconnects and when the PlayerRemoving event is fired, but it should significantly reduce the chance of encountering such issues.

After implementing this, you should continue to handle errors gracefully with pcall and always check if objects exist before using them because it’s still possible for a player or their character to be removed halfway through a script’s execution.