> For the complete documentation index, see [llms.txt](https://atiysus-organization.gitbook.io/aty-scripts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://atiysus-organization.gitbook.io/aty-scripts/inventory/reference/migration.md).

# Migration

## Migration

Switching inventory is the riskiest thing a server does. The usual reason it goes badly is a migration tool that *knew* what the old data looked like — it knew, it was wrong about one field, and three hundred people lost a weapon.

This one does not know. It **looks**.

#### Supported sources

`qb-inventory`, `ox_inventory`, `codem`, `tgiann`, `core_inventory`, `qs` — and in practice anything storing bags as JSON, because the forks differ in almost nothing that matters. Every one stores a container as one of two shapes:

```
[ { name, amount, slot, info }, … ]           an ARRAY
{ "3": { name, count, slot, metadata }, … }   a SLOT MAP
```

with field names drawn from a handful of synonyms. The importer reads the shape out of your actual rows instead of assuming one.

#### The order matters

**1. The item list.** Names are the vocabulary. Migrating a bag before the catalogue knows what a `fishing_rod` is imports a word nothing can read.

```
invmigrate items          dry run
invmigrate items write    write data/items.generated.lua
```

The generated file is a starting point to read and edit. Add it to `fxmanifest.lua` after `data/items.lua`, then `refresh` and restart.

**2. The player data.**

```
invmigrate scan                              dry run: what is out there
invmigrate run                               write — refuses on unknown names or existing containers
invmigrate run allow-unknown                 accept losing unknown names
invmigrate run force                         overwrite containers that already exist here
```

#### Importing from another inventory's tables

```
invimport                       what is on this server, and what would come across
invimport <id>                  dry-run one source
invimport <id> run              write — containers that already exist here are skipped
invimport <id> run force        overwrite them (writes export_before_force_<time>.json first)
invimport export                dump what THIS inventory holds
invrestore <file> <id> confirm  put one container back from an export file
```

The admin panel's **Migration** tab does the same thing in three steps:

1. **Pick where from** — every inventory it found on this server, with how much each one holds.
2. **See what would happen** — the dry run, in sentences: how many containers and items would come across, and what would be lost.
3. **Move it** — one button, blocked until every loss on the report has been accepted with its own switch: *leave the items this server does not know behind*, *replace what players are already carrying here*.

Nothing is written before step 3.

#### Three rules the importer keeps

**Dry run first, always.** Every command reports before it writes, and writing is a different command with a different word after it.

**An unknown name is never dropped silently.** An item in the source with no entry in the catalogue *stops the run*. You can accept the loss explicitly with `allow-unknown`, and then it is named in the report and written to the ledger. An item that vanishes quietly is an item the player can never get back.

**A container that already exists here is never overwritten** without `force`: `invimport` skips it, `invmigrate run` refuses.

{% hint style="danger" %}
Take a database backup before the writing run. The dry run is free and tells you exactly what will happen — read it.
{% endhint %}

{% hint style="info" %}
One ammo item is one round here (`Config.Ammo.mode = 'single'`, as in ox\_inventory), and an import copies counts as they are. Ammunition that came across as boxes is converted per item once it is here: `invammoconvert force <item>=<rounds>` shows what would change, `invammoconvert confirm force <item>=<rounds>` does it.
{% endhint %}

#### Keeping the old name working

Other resources call `qb-inventory` by name. Rather than editing them, install the proxy from `compat/` — see Compatibility.
