Skip to main content
TRACK B·FIVEM FUNDAMENTALS·Verified June 2026 · Lua 5.4 · ox_lib 3.x
Learning with an AI assistant?
Copies this lesson plus 2026 ground rules (no lua54 'yes', Cfx.re Portal, correct callback signatures) as a ready-to-paste mentor prompt.

Cancelling events: CancelEvent() & WasEventCanceled()

Sometimes a handler needs to veto an engine action or report that an event was rejected. CancelEvent() sets that signal, but it does not stop other handlers from running. WasEventCanceled() or Lua's TriggerEvent return value lets the code that triggered a local event inspect the result.

You'll learn
What CancelEvent() flags, why other handlers still run, how the caller checks cancellation, and the playerConnecting rejection pattern
Time
~12 minutes
Outcome
You can cancel an event from a handler, detect cancellation downstream, and pick the right tool between cancel, return, and defer
BEFORE YOU START

Build it

Make the resource folder

The server has one folder for this lesson.

Inside your server's resources folder, create this folder:

code
resources/qu_cancelling_events

Create the files

Every file named in the manifest exists.

Create this exact file layout:

code
resources/qu_cancelling_events/
fxmanifest.lua
server.lua

Write fxmanifest.lua

FiveM knows which files to load.

Open fxmanifest.lua and paste this:

code
fx_version 'cerulean'
game 'gta5'

server_script 'server.lua'

Older tutorials add a lua54 'yes' line here. As of June 2025 that setting is deprecated and ignored: Lua 5.4 is now the only Lua runtime, so you leave it out.

Write the lesson code

The topic is now represented by runnable code.

Open server.lua and paste this. Two handlers listen for the same event, and a command fires it so you can watch the chain run:

code
AddEventHandler('qu_cancelling_events:check', function(name)
print('[qu_cancelling_events] first handler checked ' .. name)
if name == 'blocked' then
    CancelEvent()
    print('[qu_cancelling_events] event cancelled')
end
end)

AddEventHandler('qu_cancelling_events:check', function(name)
print('[qu_cancelling_events] second handler still ran for ' .. name)
end)

RegisterCommand('canceltest', function(_, args)
local name = args[1] or 'allowed'
print('[qu_cancelling_events] --- firing check for ' .. name .. ' ---')
TriggerEvent('qu_cancelling_events:check', name)
print('[qu_cancelling_events] caller saw cancelled = ' .. tostring(WasEventCanceled()))
end, true)
-- The final `true` is the "restricted" flag: it locks this command behind the
-- command.canceltest ACE permission. The server console (txAdmin Live Console
-- or the FXServer window) always has permission, so run `canceltest` THERE,
-- not from in-game chat, where a normal player would be silently denied.

Start and test it

The expected proof appears in the server console.

Open server.cfg and add this line:

code
ensure qu_cancelling_events

Save, then type this into the server console (the txAdmin Live Console, or the FXServer.exe window if you launched it directly):

code
restart qu_cancelling_events

Run the blocked case first:

code
canceltest blocked

Then run the allowed case:

code
canceltest open

The two handler lines may appear in a different order. The official contract is that cancellation does not prevent other handlers from running; do not depend on registration order. The caller's final cancellation result is the assertion that matters.

Keep reading the full lesson

Sign in to start, then unlock every step of this lesson and the full FiveM School with a membership.

Still ahead in this lesson
  • How it works
  • If something went wrong
  • What you can do now
  • Try it yourself

The remainder of Cancelling events is available to FiveM School members.