Skip to content

What Happens to Pending FiveM Script Work When a Player Disconnects?

What Happens to Pending FiveM Script Work When a Player Disconnects?

Imagine a player starts a crafting action, a database request goes out, and the player disconnects before the response comes back. The callback still needs an answer: should it deliver the result, keep a durable order, undo a reservation or discard the response?

“Check whether the player exists” is a start, but it does not define the operation. A FiveM resource needs to distinguish the lifetime of the connection from the lifetime of the work. That distinction prevents rewards going to stale sessions, abandoned locks and jobs that disappear after already charging their owner.

Capture the event source before yielding

In a Lua event handler, copy the event's global source into a local variable before waiting or entering an asynchronous callback. Cfx.re documents that the global is guaranteed only during the initial event call; yielding or awaiting can reset it. The event listening guide explains the same consideration for Lua and JavaScript.

This preserves the number that originated the request. It does not preserve the connection behind that number. If you have already covered the scheduling basics in the threads and wait loops guide, this is the next lifecycle problem to address.

Keep the distinction explicit in variable names and logs. “Requesting source” describes where the request came from. It should not quietly become “the character entitled to every future result.”

Separate character identity from connection identity

The FiveM server ID, commonly exposed as source, is a transient handle according to the network and local ID reference. It is unsuitable as the sole identity for a durable business operation.

For work tied to the current connection, create a session marker and associate pending operations with it. When a delayed result returns, confirm that the session is still current before attempting player-facing work. Finding a valid player under a source number is weaker than confirming the session that started the request.

For work tied to a character, use your framework's persistent character identity and a server-created operation ID. Validate that identity when accepting the request. An account identifier alone may be insufficient on a multicharacter server, where two characters belong to the same account but have different inventories and balances.

These are application design choices, not additional FiveM native names. Implement them using the identity and persistence facilities your framework actually provides.

Decide what disconnection means for this operation

A short interaction that requires the character to remain nearby can reasonably cancel when the connection ends. A durable order that has already been accepted may need to continue and become claimable later. A request that only fills a menu can simply drop its unused result.

Write the policy before adding cleanup code. For an illustrative workbench interaction, you might reserve materials, require the same session to remain eligible, then consume and grant on successful completion. For an illustrative delivery order, you might record the accepted purchase first and allow completion while the buyer is offline.

The difference is whether departure changes the business promise. Do not let whichever callback returns first make that decision accidentally.

Also define the point beyond which cancellation is unavailable. Once an external action or committed database change has happened, “cancelled” may require compensation or reconciliation. It cannot simply mean that your Lua table no longer contains the request.

Use playerDropped to invalidate session work

The server's playerDropped event reports that a player disconnected, with the player's source available in the handler. Use the official event reference for its current arguments.

In that handler, invalidate the session marker and end the session's pending operations according to their policies. Release temporary reservations where your application owns them. Remove entries from per-session queues. Mark results that arrive later as ineligible for delivery to that connection.

Keep this cleanup safe to run more than once. A timeout may have already cancelled an operation before the disconnect event arrives. Cleanup should notice the existing terminal state and avoid issuing a second refund or releasing somebody else's reservation.

A useful design is to keep one operation record with a clear status: pending, completed or cancelled, plus enough information to reconcile failures. Avoid unrelated flags spread across a progress bar, an inventory adapter and a callback table. Those flags are likely to disagree at precisely the wrong moment.

Ignoring a result is different from stopping the work

Invalidating a session can prevent a callback from applying its result. It does not establish that an already submitted database query or HTTP request stopped executing. Check the cancellation semantics of the specific library if you need actual cancellation.

Consider a database mutation that succeeds after the player leaves. If the callback sees a missing session and returns immediately, the database has still changed. That may be correct for a durable order, but it is incorrect if the resource treats the missing notification as proof the transaction failed and later retries it.

Use an operation ID to connect retries with the original result. Make repeated completion attempts resolve to the same recorded outcome where durable effects are involved. If an external system cannot support that pattern, build a reconciliation path rather than assuming a timeout means nothing happened.

The player-facing notification should come after the server has a reliable outcome. If the player is offline, retain an appropriate receipt or claim state. A vanished notification should not turn a completed purchase into a mystery.

Account for resource restarts too

Connection cleanup cannot cover every end of life. The resource itself can stop while players remain online. Cfx.re provides onResourceStop for resource shutdown handling; check that the event refers to your own resource before cleaning up its state.

Use shutdown handling for immediate cleanup that is safe within the event. Do not depend on a lengthy asynchronous shutdown task always finishing, especially during a process crash. Durable operations should leave enough stored state for startup reconciliation.

On the next start, inspect unfinished records and decide whether to resume, cancel or investigate them. Temporary reservations should have an expiry or a recovery rule. Otherwise, an ordinary restart can leave a workshop permanently insisting that every bench is occupied by ghosts.

Test the order of events, not just the happy path

Introduce a controllable delay in your staging callback. Disconnect before the request starts, while it is pending and immediately after it commits. Reconnect and, where applicable, select another character. Repeat with a resource restart while work is pending.

For each case, check four things: the persisted outcome, any inventory or balance change, the remaining reservation, and the message delivered to the player. None should depend on an old connection still being present.

Then deliver a delayed completion twice and let a timeout race with completion. The same operation should finish once. Keep a concise log of operation ID, status transition and reason so an administrator can explain what happened later.

A resource is ready when disconnecting has an intentional outcome at every stage. The callback can arrive whenever it likes; the operation still knows who owns it, whether it may finish and where its result belongs.

Related posts

FiveM Script Support and Updates: What ‘Lifetime’ Really Means
Guide
FiveM Script Support and Updates: What ‘Lifetime’ Really Means
Escrow vs Open-Source FiveM Scripts: What You’re Really Buying
Guide
Escrow vs Open-Source FiveM Scripts: What You’re Really Buying
How Do You Get the ESX Object in 2026? Shared Object, Exports and the Line That Breaks Every Old Tutorial
Guide
How Do You Get the ESX Object in 2026? Shared Object, Exports and the Line That Breaks Every Old Tutorial
Published · Sep 21, 2026 Read more posts →