Moving a QBCore server to Qbox is mostly a database and inventory job, not a scripting one. qbx_core declares provide 'qb-core' and ships a bridge that answers the old exports['qb-core']:GetCoreObject() calls, so most qb-* job, shop and HUD resources start without edits. What does not carry over is qb-inventory: Qbox runs on ox_inventory only and refuses to work with qb-inventory running, so item definitions, every player's inventory and your stashes, trunks and gloveboxes need converting. On top of that, qbx_core.sql changes the players table and adds a player_groups table for multijob. Do all of it on a copy of the server and database first, keep the old resources/ folder and a database dump untouched, and the switch itself is an evening rather than a week.
Which framework to pick in the first place, and what each one is, is covered in FiveM frameworks: ESX vs QBCore vs Qbox. This post assumes you have already decided and have a running QBCore server with real player data you do not want to lose.
What actually changes between QBCore and Qbox#
Qbox is a continuation of QBCore, not a rewrite from nothing, which is why a migration is possible at all. The player object still has PlayerData, citizenid, charinfo, money, job and gang. The players table keeps its name and most of its columns. What moved is everything around the core.
| Area | QBCore | Qbox |
|---|---|---|
| Core resource | qb-core | qbx_core (also answers to qb-core) |
| Inventory | qb-inventory | ox_inventory, nothing else |
| Item list | qb-core/shared/items.lua | ox_inventory/data/items.lua |
| Jobs and gangs | shared/jobs.lua, gangs.lua | the same files, numeric grade keys |
| Multijob | an external resource | built in, player_groups table |
| Multicharacter | qb-multicharacter | built into qbx_core |
| Target, menus, input | qb-target, qb-menu, qb-input | ox_target and ox_lib |
The last three rows are where most of your work hides. Qbox also requires ox_lib and oxmysql to be running first, OneSync on, and a recent FXServer build. The current qbx_core manifest lists /server:10731 as a dependency, which means it will not start on an older artifact - the number moves with releases, so read fxmanifest.lua in the version you download, and see FiveM server updates and artifacts if your server is behind.
How the qb-core bridge works, and where it stops#
The bridge is a set of files under qbx_core/bridge/qb/ that rebuild the old QBCore object out of Qbox's own functions. Because qbx_core declares provide 'qb-core' in its manifest, a resource that lists qb-core as a dependency is satisfied, and exports['qb-core']:GetCoreObject() returns something that looks like the QBCore object. The bridge is on by default and controlled by one convar:
setr qbx:enableBridge "true"Things that keep working through the bridge:
QBCore.Functions.GetPlayer(source)and the player methods hanging off it:AddMoney,RemoveMoney,SetJob,SetMetaDataand the rest.- The usual server and client events a job resource listens for, such as
QBCore:Client:OnPlayerLoaded. QBCore.Shared.Jobs,GangsandVehicles, read from Qbox's own files.- The old drawtext exports,
exports['qb-core']:DrawText()andHideText(), now mapped ontoox_libtext UI. - Item functions on the player such as
Player.Functions.AddItemandRemoveItem, which the bridge forwards toox_inventoryand translates between the two item formats.
The Qbox documentation describes the framework as about 99% compatible with QB scripts, and for the core object that is fair. Where it stops is anything that reaches past the core:
- Anything calling `qb-inventory` directly.
exports['qb-inventory']:..., theinventory:server:OpenInventoryevent and qb-inventory's stash events have nothing answering them. The bridge's own inventory functions assert thatqb-inventoryis not started and fail withqb-inventory is not compatible with qbx_core. use ox_inventory instead. - `Player.Functions.SetInventory` is explicitly unsupported and throws. Scripts that rewrite a whole inventory need changing to clear-then-add.
- Resources that write SQL against QBCore tables that no longer mean the same thing - old stash tables, a job column that multijob now shadows,
player_vehiclesrows that a garage resource expects in a particular shape. - External multijob and multigang resources. Qbox has its own, and the documentation warns that unconfirmed ones can corrupt data. Remove them before the first start.
- `qb-target` exports.
ox_targetprovides compatibility forqtarget, not forqb-target. A resource callingexports['qb-target']:AddBoxZoneneedsqb-targetstill running or converting toox_target.
The bridge is a migration tool, not a permanent home. Its functions are marked deprecated in the source, and new code should call exports.qbx_core and ox_lib directly. You can convert one resource at a time, because the bridged and native calls work side by side.
Audit the resource list before touching anything#
Open resources/ and sort every folder into three piles. This is an hour with a text file and it decides how long the rest takes.
- Works unchanged. Resources that only use the core object, player money, jobs and events. Most HUDs, simple jobs, shops that sell through
AddItem, emotes, weather, voice. - Has a Qbox or ox replacement. Usually the better route than patching. Qbox maintains
qbx_versions of the commonly used QB resources. - Needs editing or dropping. Anything that talks to
qb-inventory, usesqb-menuorqb-inputheavily, or writes its own SQL against inventory and vehicle tables.
The replacements that come up on almost every server:
| QBCore resource | Qbox side | Note |
|---|---|---|
qb-inventory | ox_inventory | Required, data must convert |
qb-target | ox_target | Zones must be rewritten |
qb-menu, qb-input | ox_lib | Context menus and input dialogs |
qb-doorlock | ox_doorlock | Doors are re-entered |
qb-multicharacter | qbx_core | Built in |
qb-garages | qbx_garages | Uses qbx_vehicles |
qb-vehiclekeys | qbx_vehiclekeys | |
qb-policejob | qbx_police | |
qb-ambulancejob | qbx_ambulancejob | Pairs with qbx_medical |
ox_inventory's Qbox integration also asserts that qbx_vehicles is running, so add it even if you keep your own garage resource. For paid scripts, check the author's page before assuming anything: many advertise Qbox support through a config switch, and an escrowed script you cannot edit either supports Qbox or it does not. FiveM escrow and asset licensing covers what you can and cannot change in those.
The fastest way to build pile three is a search. Run this from the resources/ folder on a copy of the server and read every hit:
$ grep -rn --include=*.lua -e "qb-inventory" -e "qb-target" -e "SetInventory" .$ grep -rn --include=*.lua -e "stashitems" -e "trunkitems" -e "gloveboxitems" .$ grep -rn --include=*.lua -e "QBCore.Shared.Items\[" .The last one matters because some resources add items at runtime by writing into QBCore.Shared.Items. Under Qbox, items belong to ox_inventory, and those runtime additions do nothing useful.
Build the test server first#
Do not migrate the live server in place. Build a second server, give it a copy of the database and a copy of resources/, and do every step below there first. The general method - what to copy, what must differ, how small it can be - is in running a test server beside production. For this migration specifically:
- A separate database, always. The test server must point its
mysql_connection_stringat a copy, never at the production schema. The SQL steps below alter tables, and running them against live data by accident is the one mistake that turns an evening into a weekend. - A fresh dump of production to seed it. Use
mysqldumpwith--single-transactionso you do not lock players out while it runs, as described in mysqldump backup and restore. - Close it to the public. Set
sv_maxclientslow, add a password-style check through your Discord whitelist or simply do not list it, and give it its own hostname so nobody connects to the wrong one. - Log in as a real character. Testing on a fresh character proves nothing about conversion. Pick a few characters with full inventories, weapons, a car with items in the trunk and a job grade above zero, and check every one of them after conversion.
On RE:NODE each server is its own container with its own database slot, so the test server's copy cannot see the production database unless you give it those credentials. Import the dump through "Open in phpMyAdmin" on the test server's database tab, or from the command line with the generated host and user.
Database changes Qbox makes#
Back up first. Every step in this section is easy to apply and awkward to reverse.
$ mysqldump --single-transaction --routines -h DB_HOST -u DB_USER -p qbcore \ > qbcore-before-qbox.sqlThen import qbx_core.sql from the qbx_core release you are installing. Against an existing QBCore database it does three things that matter. It adds a last_logged_out column (and in current versions a userId column) to players. It changes players so the table and its key columns use the utf8mb4_unicode_ci collation. And it creates player_groups, which stores every job and gang a character holds, with a foreign key on citizenid back to players.
That foreign key is where most migrations stall. A foreign key needs both columns to use the same collation, and plenty of QBCore databases were created with utf8mb4_general_ci. If the import fails with a foreign key error, check and fix the collation:
SELECT TABLE_NAME, COLUMN_NAME, COLLATION_NAMEFROM information_schema.COLUMNSWHERE TABLE_SCHEMA = 'qbcore' AND COLUMN_NAME = 'citizenid';ALTER TABLE players MODIFY citizenid VARCHAR(50) NOT NULL COLLATE utf8mb4_unicode_ci;Run the same MODIFY on any other table whose citizenid column still reports utf8mb4_general_ci, keeping each column's existing type and nullability, then import qbx_core.sql again. The reasons collations clash at all are covered in MySQL utf8mb4 and collations.
Next, the jobs and gangs. Qbox wants grade keys in shared/jobs.lua and shared/gangs.lua as numbers, where QBCore used strings:
police = { label = 'LSPD', defaultDuty = true, grades = { [0] = { name = 'Recruit', payment = 50 }, -- QBCore had ['0'] [1] = { name = 'Officer', payment = 75 }, [4] = { name = 'Chief', isboss = true, payment = 150 }, },},Copy your custom jobs and gangs across before the first start, then fill the new table. With the server running, type this in the txAdmin or live console:
convertjobsIt copies each character's current job and gang from the players table into player_groups, it only runs from the server console, and it is safe to run twice. Two convars decide how multijob behaves afterwards: qbx:max_jobs_per_player and qbx:max_gangs_per_player, both 1 by default.
player_vehicles is left alone: qbx_vehicles creates it only if it does not exist. ox_inventory adds a trunk and a glovebox column to it, and an inventory column to players if one is missing, on its first start.
Converting qb-inventory to ox_inventory#
This is the part that needs the most care, and the part where tutorials disagree most, because the tools changed in 2024. Three separate things move: item definitions, player inventories, and everything else (stashes, trunks, gloveboxes).
Item definitions
Paste your QBCore item table into qbx_core/shared/items.lua. On the next start the bridge converts every item that ox_inventory does not already know into ox_inventory's format and writes them to qbx_core/converted.lua, with a console warning telling you how many it added. It skips names that look like weapons, attachments and ammo, because ox_inventory has its own weapon definitions. Review the file, copy the entries into ox_inventory/data/items.lua, empty shared/items.lua again, and restart. A converted entry looks like this:
['sandwich'] = { label = 'Sandwich', weight = 200, stack = true, close = true, description = 'Nice bread for your stomach', client = { status = { hunger = 200000 }, image = 'sandwich.png', },},Usable items still work through the bridge's CreateUseableItem, but the hunger and thirst values from your consumables resource will not apply themselves; check each food item once in game. Copy item images from qb-inventory/html/images into ox_inventory/web/images, or every converted item shows a blank square.
Player inventories
QBCore and ox_inventory both store a player's inventory as JSON in players.inventory, but the fields differ:
{"name": "water_bottle", "amount": 3, "info": {}, "slot": 1, "type": "item"}{"name": "water_bottle", "count": 3, "metadata": {}, "slot": 1}The first line is QBCore, the second ox_inventory. When ox_inventory loads an unconverted character it stops with Inventory for player.X contains invalid data. Ensure you have converted inventories to the correct format. Current ox_inventory releases ship a convertinventory console command, but its only options are esx and esxproperty; run it with no argument and it prints that list. The QBCore converter was removed in August 2024, and v2.41.0 is the last release that has convertinventory qb. It renamed amount to count and info to metadata, turned QBCore cash into the money item, and gave weapons a serial and durability from their old quality.
The practical routes are to run that old release once on the test server purely to convert, then replace it with a current ox_inventory, or to write the same field mapping yourself in SQL or Lua. Either way, compare a handful of characters before and after. Once converted, cash lives in two places that ox_inventory keeps in sync: the money item and PlayerData.money.cash.
Stashes, trunks and gloveboxes
This is where data is most often lost. Older qb-inventory versions kept these in stashitems, trunkitems and gloveboxitems; the old converter moved trunks and gloveboxes into player_vehicles but never handled stashes. Current qb-inventory (2.x) stores all of them in one inventories table keyed by an identifier string, which no official converter reads. Under Qbox, ox_inventory stores stashes in its own ox_inventory table and trunks and gloveboxes in player_vehicles, keyed by the vehicle's id.
So decide what is worth keeping. Personal and job stashes usually are, and they need a small script that reads each inventories row, converts the items as above and inserts them under the stash name your ox_inventory stash definitions use. Many servers decide trunk and glovebox contents are not worth a script and announce they will be emptied. That is a legitimate choice, but make it on purpose and tell players before the switch, not afterwards.
Cutover day, in order#
Once the test server has run the whole process and survived a session with real testers, the live switch is a checklist:
- Announce a maintenance window and close the server with txAdmin's whitelist or by stopping it.
- Take a final
mysqldumpand a panel backup of the server files. Download both. - Run the SQL steps, in the order that worked on the test server.
- Swap
resources/for the tested folder, and bring acrossserver.cfg,ox.cfgandpermissions.cfgfrom it. - Start with the console open.
ensure oxmysql,ox_lib,qbx_coreandox_inventorymust come up before anything that depends on them. Reading the console covers what to look for. - Run
convertjobsand the inventory conversion you rehearsed. - Log in as three of the characters you checked on the test server. Open the inventory, a stash and a trunk.
- Open to players, and watch the console and
resmonfor the first hour.
Rollback plan#
Write the rollback down before you start, because the moment you need it is the moment you will not think clearly. A migration is reversible only if both halves of the old server still exist untouched.
- Files. Keep the old
resources/folder andserver.cfgas an archive, not overwritten. Switching back is restoring that folder. - Database. Restore
qbcore-before-qbox.sqlinto the database. A forward fix is not a rollback - the converted inventory JSON, the new collation andplayer_groupswill not undo themselves. - A decision deadline. Pick the point after which you fix forward instead. Players who have played on Qbox for a day have data a restore would erase. A sensible rule: roll back freely during the maintenance window, and only for data loss after it.
On RE:NODE the panel backup covers files and the dump covers the database, so take both. A backup can be locked against rotation so the pre-migration copy survives your scheduled backups, but test the restore on the test server before you rely on it.
Troubleshooting#
The errors that come up in nearly every migration:
| Symptom | Cause |
|---|---|
qb-inventory is not compatible with qbx_core | qb-inventory still started |
contains invalid data on login | Inventory still in QBCore format |
Foreign key error importing qbx_core.sql | citizenid collations differ |
| Job grade shows as nil | Grade keys still strings |
| Items show blank squares | Images not copied |
| Players lost their job | cleanPlayerGroups on with jobs missing |
Two more are quieter. A resource that silently does nothing usually calls QBCore.Shared.Items to check an item exists; replace that lookup with exports.ox_inventory:Items(). And duplicate folders - an old qb-inventory in a bracketed folder you forgot about - start whichever FXServer finds first, so delete the old one rather than leaving it unensured.
FAQ#
Can I run Qbox without the qb-core bridge?
Yes, set qbx:enableBridge to false, but only once nothing on the server calls qb-core any more. Most servers keep it on for months and convert resources gradually.
Do I lose character data moving to Qbox?
Not if you convert properly. Characters, money, metadata, jobs and vehicles stay in the same tables. Inventories, stashes, trunks and gloveboxes are the data at risk, because they change format and tables.
Can I keep qb-inventory on Qbox?
No. qbx_core refuses to work with qb-inventory running, and ox_inventory is the only inventory Qbox supports.
Will my paid QBCore scripts work on Qbox?
Many do through the bridge, and many authors ship a Qbox option. The ones that break are those that call qb-inventory or qb-target directly. Check the author's notes and test on the copy.
How long does a migration take?
A server with a modest resource list is a weekend of preparation on the test server and a one or two hour maintenance window. Large servers with dozens of inventory-dependent scripts take longer, mostly in rewriting those scripts.
Can I go back to QBCore after switching?
Only by restoring the pre-migration database dump and the old resources/ folder, which erases anything players did after the switch. Decide your rollback cut-off before you start.


