F5 StudioF5 Studio
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