Grounded on the current Overextended API

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)
end

Common 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

Yes. ox_lib is framework-agnostic and plenty of standalone resources use it. You can generate ox_lib-only code without selecting a framework, and SwisserAI will scope to the ox_lib API surface without assuming player state shape.
Our generation pipeline is grounded on the current Overextended ox_lib API surface rather than free-form completion over the library name. We treat ox_lib as a closed vocabulary: the model picks from real calls, not a plausible hallucination of them. We also maintain an internal test set of ox_lib snippets that we regression-check whenever the ox_lib repo ships breaking changes.
The current stable Overextended release. If your server pins an older version you can specify it in the prompt and SwisserAI will stick to that older surface.
Yes. Item definitions for data/items.lua, server-side RegisterUsableItem hooks wrapped as ox_inventory:RegisterHook, stash registration, and metadata-aware code. Crafting tables are supported too.
Yes. Box zones, sphere zones, model-based targets, and per-entity attachments. Options use the current ox_target structure with icon, label, distance, canInteract, and onSelect.
Generated resources can register doors with proper auth predicates (job names, grade minima, items). State-bag sync is handled no custom tick loops.
Paste the relevant section of the ox_lib docs or source in your prompt. SwisserAI will use that as the source of truth rather than its baseline. For widespread gaps, tell us at support@swisser.dev API coverage is an active priority.

Stop debugging invented ox_lib calls

250 free credits. Generate, review, ship. ox_lib code grounded on the real API.