Skip to main content

Troubleshooting

Most issues come from one of five sources: boot order, framework/inventory detection, admin access mapping, money/item configuration, or a code-state edge case (expiry, uses, private target). Work through the relevant section below.

The first thing to do for almost any problem is enable debug and read the server console:

config/config.lua
F5Cfg.Debug.enabled = true
-- the categories below are on by default; PERF is off

Nothing Happens / Resource Is Inert​

Symptom: /redeem or /redeemadmin does nothing; no panel opens.

1. Framework / inventory detected?​

The bridge runs detection once at startup. With the BRIDGE and INIT categories on you should see:

[SERVER][BRIDGE] detected framework=qb inventory=qb
[SERVER][INIT] f5_code server ready (framework=qb inventory=qb)

If instead you see an inert message, the resource didn't initialize:

[SERVER][ERROR] [ERR]  [BRIDGE] no supported framework detected (esx/qb/qbx) — resource inert
[SERVER][ERROR] [ERR] [BRIDGE] no supported inventory detected for framework esx

2. Boot order​

f5_redeemcode must start after oxmysql, your framework, and your inventory. A reversed order means detection runs before those resources exist.

server.cfg
ensure oxmysql
ensure qb-core
ensure qb-inventory
ensure f5_redeemcode

3. Wrong adapter detected?​

If detection picked the wrong inventory (e.g. esx_native while you actually run ox_inventory), force it:

config/config.lua
F5Cfg.Framework.inventory = 'ox'
F5Cfg.Framework.mode = 'qb' -- only if framework detection is also wrong

See Framework Compatibility.

Config / Errors About a Missing File​

Symptom: Startup errors like couldn't load config.lua, or F5Cfg being nil.

Both config files live in the config/ folder and the manifest loads them from there (config/config.lua, config/config_webhooks.lua). If you moved or renamed them, put them back — or update the paths in fxmanifest.lua to match. Don't reference config.lua from the resource root.

Database Errors / No Driver​

Symptom: IO logs about DB failures, or [sql_bridge] no MySQL driver started….

The SQL bridge waits up to 30 s for oxmysql, mysql-async or ghmattimysql to start. If none is up in time, DB calls throw. Ensure a supported driver starts before f5_redeemcode:

[SERVER][IO] [sql_bridge] driver detected: oxmysql

If you disabled autoCreateTables, make sure you imported code.sql and are aware migrations don't run — keep autoCreateTables = true unless you manage the schema yourself. See Configuration → Database.

Admin Panel Denied​

Symptom: /redeemadmin shows "You do not have permission to do this."

Access = passes the ACE permission OR belongs to a listed framework group:

config/config.lua
F5Cfg.Admin = {
acePermission = 'f5code.admin',
frameworkGroups = { 'admin', 'god' },
}
  • Using the ACE path? Grant it: add_ace group.admin f5code.admin allow in server.cfg, and make sure your player is in group.admin.
  • Using framework groups? Confirm your character's group is one of frameworkGroups (QB PlayerData.job/permission, ESX group, etc.).
  • Set acePermission = '' to disable the ACE path, or frameworkGroups = {} to disable the group path — but don't disable both, or nobody has access.

With the SECURITY category on, a denial logs admin reject … reason=no_permission.

"Invalid or Expired Code"​

A code returns redeem_invalid / redeem_expired / redeem_max_uses / redeem_private / redeem_already_used. Each maps to a specific rule — with the CODE category on, the server logs the exact reason:

MessageCauseFix
redeem_invalidCode doesn't exist or was deletedCheck spelling; confirm it's live in Active Codes
redeem_expiredPast its expiry dateEdit the code and extend/clear the expiry
redeem_max_usesReached its use capRaise max_uses (or 0 for unlimited)
redeem_privatePlayer's Citizen ID isn't a targetAdd their Citizen ID to the code's targets
redeem_already_usedThis player already redeemed itExpected — each player may redeem a code once
redeem_cooldownRetried too fastWait cooldownMs; raise it only if needed
Case sensitivity

If a code that "should" match is rejected, check F5Cfg.Codes.caseInsensitive. With it true (default) SUMMER and summer match; with it false they don't.

Money Not Granted​

Symptom: Redeem succeeds but the player's balance doesn't change.

  • The target money account must be active for your framework. crypto has no ESX account and blackmoney has none on QB/QBox, so those types are skipped there. See Framework Compatibility → Money.
  • For legacy single-amount codes, payout goes to F5Cfg.Money.payoutType — make sure it's a valid, active type (falls back to bank, then the first active type).
  • With the REDEEM category on, a failed credit logs failed to add money …. That usually means the account key doesn't match your framework's real account name — check the accounts mapping in F5Cfg.Money.types.

Items Not Granted / "Not Enough Inventory Space"​

  • redeem_inventory_full means the player couldn't carry all items — the redeem is refused and nothing is granted (by design). Have them free space and retry.
  • If items silently don't appear, confirm the item names exist in your inventory and the inventory adapter is the right one. A REDEEM log failed to add item … points at a bad item name or a full slot.
  • Amounts are clamped to 1 … F5Cfg.Rewards.maxItemAmount; distinct items beyond maxItems are dropped at create time.

No Item Images In The Panels​

Item icons use the detected inventory's image path. If they're missing or from the wrong inventory, override it:

config/config.lua
F5Cfg.Inventory = {
imageUrl = 'nui://ox_inventory/web/images/%s.png',
}

%s is the item name. See the per-inventory paths in Framework Compatibility → Inventories.

Private Code Won't Save / Target "Doesn't Exist"​

Symptom: Creating a private code fails with admin_targets_not_found or admin_target_unverifiable.

  • admin_targets_not_found — one of the Citizen IDs isn't in the player database. Double-check the ID, or use Choose from list to pick an online player.
  • admin_target_unverifiable — the bridge couldn't query the player table (wrong table/column for a fork, or a DB error). For a custom framework, set playersTable / uidColumn. See Framework Compatibility → Custom framework.
  • To skip DB validation entirely (trust the entered IDs), set F5Cfg.Codes.validatePrivateTarget = false.

Webhooks Not Sending​

  • Confirm the master switch: F5Cfg.Admin.auditWebhook = true.
  • Set Webhooks.defaultUrl (or the event's own url) to a real Discord webhook.
  • The URL must match Webhooks.urlValidationPattern; a rejected URL logs url rejected by pattern under the WEBHOOK category.
  • Check the event's enabled = true.

See Webhooks.

A Deleted Code's Name Won't Free Up​

Reusing a deleted code's name relies on the code_active generated column, which needs MySQL 5.7+ / MariaDB 10.2+. On older servers the migration is skipped (you'll see a [DB] error about it) and the legacy unique key is kept, so old names stay reserved. Upgrade your database engine to enable name reuse.

Still Stuck?​

  • Turn on F5Cfg.Debug.enabled and the SECURITY, CODE, REDEEM, ADMIN and IO categories, then reproduce the issue and read the server console — the exact rejection reason is almost always printed.
  • Join the F5 Studio Discord for support.

See Also​