Upgrade Scripts Docs

#Troubleshooting

Before anything else, restart the resource and read the server console. It prints the version it loaded, the framework, inventory and garage script it detected, the result of a full config check, and exactly what your level settings resolved to. Most problems are visible there.

Setting Config.Debug = true adds a line for every XP grant, every admin permission check and every purchase, each naming the value or rule that decided the outcome.

#Players are leveling far too quickly

Check the level line the console prints on start:

[Upgrade-Rewards] Level system: mode static | XP needed 1->2: 2000, ... | XP per playtime reward: 200 (every 60 min)

Almost always this is Config.LevelSystem.XPPerLevel being edited while Mode is still 'scaling'. Only the values belonging to the chosen mode are read, so the default 100 XP curve stays in force and a single playtime reward is enough for a whole level. For 2,000 XP per level you need both:

Config.LevelSystem.Mode       = 'static'
Config.LevelSystem.XPPerLevel = 2000

The resource prints a warning of its own when one playtime reward is enough to reach level 2, so look for that too.

#The XP bar shows one number but players level at another

That was fixed in 1.5.2. The threshold used to be stored per player when their record was created, so changing the config never affected existing players. It is now calculated from your config every time it is read. If you are still seeing it, you are running an older build - check the version line on start.

#The admin panel shows identifiers instead of names

Fixed in 1.5.2, most often seen on ESX. Name lookups now cope with the license: prefix being present or absent, and every player's FiveM name is stored when they load in, so there is always something to show.

Names fill in as players connect. A record for someone who has not joined since you updated shows their identifier until their next login. Turn on Config.Debug and open the panel to see how many names resolved and from which table.

#A rewarded vehicle never appears in the garage

Set a real garage name for your framework in Config.Garage.DefaultGarage. The ESX entry defaults to false, which leaves the garage column empty - some ESX garages treat that as "available anywhere", but many need a named garage.

Check what was detected on start:

[Upgrade-Rewards] Vehicle rewards -> owned_vehicles (garage column: parking, stored column: stored, garage script: loaf_garage)

If the garage column is wrong for your script, override it with Config.Garage.Columns.garage. The vehicle row itself is written to owned_vehicles or player_vehicles, so you can confirm the vehicle was created even when the garage script does not list it.

#Someone who should be view-only can still make changes

Add their identifier to Config.AdminPanel.View.Identifiers. Listing an identifier pins that person's tier, which overrides any group they hold. Without that, being in a group named in Modify.Groups is enough on its own.

Remember the default Modify.Groups includes god and superadmin, so testing on your own account usually needs your identifier under View. Turning on Config.Debug prints which rule granted or denied each check.

#An admin cannot open the panel at all

/rewards-admin needs a match in either tier. Check their framework group against Config.AdminPanel.View.Groups, or grant them the view ace:

add_ace identifier.license:abc123... upgrade_rewards.view allow

#Money from a loot case never arrives

Cash entries must use type = "cash". An entry written as type = "item", item = "money" will not pay out on any framework. The config check flags these by name on start.

#A shop item hands out the wrong quantity

Fixed in 1.5.4. Purchases used to be matched by item name across every unlocked shop, so the same item name in two shops could resolve to the cheaper one. Purchases are now keyed to the exact shop and slot clicked.

#Playtime in the admin panel is behind what the player sees

Fixed in 1.5.3. The panel read the database copy, which is only written every five minutes. It now shows the live counter.

#Points or playtime lost after a restart

Playtime is saved when the resource stops, on every reward, and on disconnect, so at most a minute is at risk. If you are losing more than that, you are on a build before 1.5.4.

#The "get out of jail" item says the player is not in jail

Your jail script stores the sentence under a different metadata key. Set Config.Jail.MetadataKey to match it - qb-policejob and qb-prison use injail, some ESX jails use jail. The item only works with jail scripts that keep the sentence in framework metadata.

#Nothing arrives in Discord

Check Config.Webhooks.Enabled is true and that the event you expect has either its own url or a DefaultURL to fall back on. With Config.Debug on, the resource prints the HTTP status of any webhook that fails, which usually reveals a truncated URL or a webhook deleted in Discord.

#Warning about duplicate referral codes on start

[Upgrade-Rewards] Could not add idx_upgrade_rewards_refid on upgrade_rewards

Your database holds duplicate referral codes left over from a bug fixed in 1.5.1. Everything keeps working, the resource just cannot enforce uniqueness until they are cleared. Find them with:

SELECT refid, COUNT(*) c FROM upgrade_rewards GROUP BY refid HAVING c > 1;

Then clear the losing rows - a new code is issued on their next join:

UPDATE upgrade_rewards SET refid = NULL WHERE license = '<license>';

#Still stuck

Open a ticket with your server console output from a fresh restart and Config.Debug set to true. The startup lines alone identify the version, framework, inventory, garage script and level settings in use, which answers most questions immediately.