ox_lib + SwisserAI
The #1 complaint about AI in FiveM forums is hallucinated ox_lib functions. We scope generation to the real Overextended API surface if a call would not exist, it does not get emitted.
The ox_lib hallucination problem
Spend ten minutes on forum.cfx.re and you will see the pattern: a developer pastes AI-written Lua, the server throws “attempt to call a nil value (field notify_player)” on load, and the thread turns into a 30-post debate about whether ox_lib “removed” a function. The function never existed.
ox_lib is exactly the kind of target that generic LLMs struggle with. It is popular enough to show up in training data under dozens of tutorials, versions, and blog posts and small enough that the model never really nails which API is current versus which was renamed two releases ago. The result is confident code that calls invented methods.
SwisserAI treats ox_lib as a closed vocabulary. Generations are grounded on the current Overextended ox_lib API surface lib.notify, lib.callback, lib.registerContext, the whole menu system, the cache helpers, the interface modules. When the model is tempted to invent, the grounding pushes it back to the real call. No “lib.createMenu.” No “ox_lib.notify_player.”
We frame this as an internal discipline rather than a magic guarantee nothing catches every edge case, and the ox_lib repo ships changes. When in doubt, always review the diff before deploying.
ox_lib + Overextended coverage
lib.notify
Client and server notifications with type, duration, icon, and position. Correct argument shape, every time.
lib.callback
lib.callback.register on the server, lib.callback / lib.callback.await on the client. Awaited promises, no dangling cbs.
lib.registerContext
Context menus with nested submenus, onSelect handlers, arrow progression, and keepOpen flags.
lib.addRadialItem
Radial menu integration for ox_lib with proper remove / clear lifecycle on resource stop.
ox_inventory integration
exports.ox_inventory:AddItem, CanCarryItem, RegisterStash, CreateDrop, usable-item hooks. Metadata-aware.
ox_target zones and models
addBoxZone, addSphereZone, addModel, addEntity. Proper option structures with distance, canInteract predicates, and icons.
ox_doorlock and state bags
Door registration, state-bag driven sync keys, and the correct auth guards for lock state changes.
oxmysql and ox_core helpers
exports.oxmysql:query_async with prepared placeholders, and ox_core helpers where your stack uses them.
ox_lib code that runs
Every snippet below is a real call against the current ox_lib API surface.
Client notification
lib.notify({
title = 'Crate delivered',
description = 'Earned $1,200 for the run.',
type = 'success',
position = 'top',
duration = 5000,
})Server callback + client await
-- server
lib.callback.register('swisser:server:priceQuote', function(source, itemName)
local prices = { radio = 2500, armor = 3000 }
return prices[itemName] or 0
end)
-- client
local price = lib.callback.await('swisser:server:priceQuote', false, 'radio')
lib.notify({ title = ('Radio costs $%s'):format(price), type = 'inform' })Context menu with submenu
lib.registerContext({
id = 'dealer_menu',
title = 'Dealer',
options = {
{
title = 'Buy',
description = 'Goods for sale',
icon = 'cart-shopping',
menu = 'dealer_buy',
},
{
title = 'Sell',
description = 'Turn stock into cash',
icon = 'hand-holding-dollar',
onSelect = function()
TriggerServerEvent('swisser:server:openSellScreen')
end,
},
},
})
lib.registerContext({
id = 'dealer_buy',
title = 'Buy',
menu = 'dealer_menu',
options = {
{ title = 'Radio $2,500', onSelect = function() TriggerServerEvent('swisser:server:buy', 'radio') end },
{ title = 'Armor $3,000', onSelect = function() TriggerServerEvent('swisser:server:buy', 'armor') end },
},
})
lib.showContext('dealer_menu')ox_target zone
exports.ox_target:addBoxZone({
coords = vec3(-47.4, -1757.3, 29.4),
size = vec3(1.5, 1.5, 2.0),
rotation = 0,
debug = false,
options = {
{
name = 'swisser:24_7_shop',
label = 'Open Shop',
icon = 'fa-solid fa-basket-shopping',
distance = 1.8,
onSelect = function()
TriggerEvent('swisser:client:open247')
end,
},
},
})ox_inventory stash
-- server: register once on resource start
exports.ox_inventory:RegisterStash('gang_stash_ballas', 'Ballas Stash', 50, 100000)
-- client: open it
TriggerServerEvent('ox_inventory:openInventory', 'stash', 'gang_stash_ballas')oxmysql prepared query
local rows = exports.oxmysql:query_await(
'SELECT id, label FROM swisser_items WHERE owner = ? LIMIT 50',
{ identifier }
)
for i = 1, #rows do
print(rows[i].id, rows[i].label)
endCommon hallucinations
If you have used any AI tool with ox_lib, these will look familiar.
Invented ox_lib functions
Generic AI cheerfully emits functions like ox_lib.notify_player or lib.createMenu that do not exist. SwisserAI generates against the current ox_lib surface if a call would hallucinate, it does not get written.
Legacy wrapper patterns
Early ox_lib had a lib = exports.ox_lib:load() style bootstrap in some builds. Modern ox_lib injects the lib global. Code that mixes the two silently breaks.
Wrong lib.callback direction
lib.callback.register is server-side only; on the client you use lib.callback / lib.callback.await. AI that flips these ships broken callbacks.
ox_target option drift
The option shape evolved (distance, canInteract, onSelect replaced older action). Snippets that mix versions throw silently on hover.
Frequently Asked Questions
Stop debugging invented ox_lib calls
250 free credits. Generate, review, ship. ox_lib code grounded on the real API.