UltraSync Migration
UltraSync Migration
Section titled “UltraSync Migration”If your network was previously running UltraSync, Link Cable can import every player’s UltraSync record directly from MongoDB into its player-core lane. The migration is one-shot, safe by default (online players are skipped), and creates pre-migration backups automatically before overwriting any existing Link Cable data.
This page covers the migration command, the safety rules, and the recommended order of operations.
What Migrates
Section titled “What Migrates”The migration imports into the player-core lane only. The fields populated come from whatever the UltraSync record had for that player:
- inventory
- ender chest
- health
- food level and saturation (
foodTickTimerandfoodExhaustionLevelreset to defaults) - XP — total, level, and progress
- game mode (
survival,creative,adventure,spectator) andpreviousPlayerGameType - Accessories mod data, when present in UltraSync’s
trinketsfield, mapped into the Fabric Attachment API slot Accessories uses
The player-core lane in Link Cable is broader than UltraSync stored — abilities, recipe book, score, Cardinal Components data, and other Fabric Attachment API entries aren’t in the UltraSync schema, so those fields stay at their defaults on the migrated player. Anything the player picks up after first login (recipes, etc.) is captured in the next snapshot.
The migration does not invent Cobblemon data. Existing Cobblemon snapshot lanes — party, PC, general, Pokedex, and Molang — stay intact. If a migrated player already has Link Cable Cobblemon state, it’s preserved. If they don’t, those lanes start empty and will fill in normally as the player plays.
Command
Section titled “Command”/linkcable migrate ultrasync <mongoUri|active> [limit]Examples:
/linkcable migrate ultrasync active/linkcable migrate ultrasync "mongodb://localhost:27017"/linkcable migrate ultrasync active 500Use active when UltraSync lives on the same MongoDB deployment Cobblemon and Link Cable already use. Otherwise pass a full Mongo connection string in quotes.
The optional limit argument caps how many records the migration processes. Use it for validation runs (limit 1 to migrate one record and verify) and progressive rollouts (limit 500 to chunk a large dataset).
The database and collection are fixed:
| Field | Value |
|---|---|
| Database | UltraSync |
| Collection | users |
These match the UltraSync exports. Override them in config.json only if you’ve manually relocated the data — see Configuration.
Safety Rules
Section titled “Safety Rules”The migration is conservative on purpose. The following rules are enforced and not configurable:
- Players online anywhere on the network are skipped. A presence check rejects them before any state is touched.
- Players with a runtime state other than
OFFLINEare skipped. Mid-transfer or in-recovery players also fall into this bucket. - Each player’s migration is serialized behind a distributed lock — the same lock live sync uses. If the lock can’t be acquired within the timeout, that player is skipped (not failed) and you can re-run the command later.
- Pre-migration backups are taken automatically for any player who already has a Link Cable snapshot. The backup’s reason is
pre-ultrasync-migration— find it via/linkcable backup list <player>if you need to roll back. - Only the player-core lane is touched. Party, PC, general, Pokedex, and Molang are preserved verbatim from the existing snapshot (or stay empty for brand-new accounts).
What this means in practice: you can run /linkcable migrate ultrasync active on a live network with players online and not worry about damaging anyone’s state. The online players are skipped; they’ll either get migrated next time you run the command or you can flip on ultraSyncJoinMigrationEnabled (see below) to migrate them on next login.
Recommended Migration Flow
Section titled “Recommended Migration Flow”1. Validate on One Account First
Section titled “1. Validate on One Account First”Pick an UltraSync account that’s never logged into Link Cable. Confirm they’re offline. Run:
/linkcable migrate ultrasync active 1This migrates exactly one record. Verify the resulting player state is correct:
- Have the player log in.
- Confirm inventory, ender chest, health, hunger, XP, and game mode match what UltraSync had stored.
- Confirm Cobblemon lanes (party, PC, Pokedex) are empty if the account never used Link Cable, or unchanged if they had.
If any lane is wrong, stop and investigate before running the bulk migration. Issues at this stage almost always mean the UltraSync collection name or schema doesn’t match what Link Cable expects.
2. Bulk Migrate
Section titled “2. Bulk Migrate”Once the validation account looks right:
/linkcable migrate ultrasync activeWithout a limit, this processes every record in the users collection that isn’t already migrated and isn’t online. Watch the console for the summary message and any per-player failures.
For very large UltraSync datasets, chunk the migration with limit:
/linkcable migrate ultrasync active 1000/linkcable migrate ultrasync active 1000/linkcable migrate ultrasync active 1000…Each run picks up where the previous one left off (online and already-migrated players are skipped, so re-running is idempotent).
3. Catch Stragglers via Join Migration
Section titled “3. Catch Stragglers via Join Migration”For online players who got skipped during the bulk run, enable join migration:
"ultraSyncJoinMigrationEnabled": true(In config.json on the orchestrator, then restart the orchestrator.)
When this is true, any player who logs in and doesn’t have a Link Cable snapshot and does have an UltraSync record gets migrated on first join. Pre-migration backup rules still apply.
After the network has been live long enough that every active player has logged in (typically a few weeks), turn this flag back off. It’s intended as a transition mechanism, not a permanent feature.
Examples
Section titled “Examples”UltraSync on the same Mongo as Cobblemon:
/linkcable migrate ultrasync activeUltraSync on a separate Mongo instance:
/linkcable migrate ultrasync "mongodb://ultrasync-host:27017"Validation run — migrate one record:
/linkcable migrate ultrasync active 1Chunked bulk migration:
/linkcable migrate ultrasync active 500(Run repeatedly until the per-run count drops to zero.)
What’s Logged
Section titled “What’s Logged”The command echoes a single completion line back to the actor:
UltraSync migration finished: scanned=12 migrated=10 skipped=2Or, if any record failed:
UltraSync migration finished with failures: scanned=12 migrated=9 skipped=2 failed=1The four counts mean:
scanned— how many UltraSync records the command read.migrated— successfully imported into Link Cable.skipped— skipped intentionally (online, non-OFFLINEstate, lock contention, no-op because the existing snapshot is already current).failed— the migration tried but couldn’t complete. Failures are listed underneath as separatefailurelines (up to 10 per run).
The two failure modes the migration produces are:
missing _id in UltraSync document— the UltraSync record didn’t have a_id(player UUID) field. Likely a damaged or hand-edited record.failed pre-migration backup for <uuid>: <reason>— the pre-migration backup couldn’t be saved, so the migration aborted to avoid losing state. The nested reason points at the underlying storage issue.
Online players, locked players, and already-migrated players are skipped, not failed. If you re-run the command, skipped players will be reconsidered next pass; failed players need investigation first.
Re-running the command is safe — already-migrated players are skipped on subsequent passes (the merge step is a no-op when the existing snapshot already matches).
Storage Model
Section titled “Storage Model”A common question: why doesn’t Link Cable just reuse Cobblemon’s existing storage backend?
Link Cable needs a few things Cobblemon’s persistence model doesn’t natively provide:
- one aggregate versioned snapshot per player, across all lanes
- owner epoch fencing to stop stale writers
- Redis cache and runtime state for hot-cache handoffs
- backup, export, and import support
- verified writes across both Cobblemon and player-core lanes
So canonical persistence is owned by Ceremony storage providers, with Cobblemon’s storage remaining the in-memory model and serialization format Link Cable works with. The migration writes through that path — it doesn’t directly poke Cobblemon’s collections, and it doesn’t bypass the safety mechanisms.
Troubleshooting
Section titled “Troubleshooting”Migration succeeds but the player has no inventory after first login : The UltraSync record might not have included player-core data for that account, or the schema didn’t match. Check the migration log for that player’s UUID — if it logged a successful migrate, the data was found. If it didn’t, the account didn’t have an UltraSync record to migrate.
active requires Ceremony storage to be configured for MongoDB
: You passed active for the Mongo URI but Ceremony isn’t using MongoDB on this backend. Either fix Ceremony’s storage configuration to point at MongoDB, or pass an explicit Mongo URI in quotes.
Cannot connect to the Mongo URI you passed
: The connection string is wrong, the Mongo host is down, or this backend can’t reach it. Test with mongosh from the same host. If you’re using active, confirm Cobblemon’s own Mongo connection is working from this backend.
Many players being skipped
: This is usually fine — skipped means online, mid-transfer, locked, or already up-to-date. If you expect those players to migrate, confirm they’re actually offline and the existing snapshot doesn’t already contain their UltraSync data, then re-run.
missing _id in UltraSync document failures
: The corresponding UltraSync record is missing the _id field that holds the player UUID. Likely a partial export or hand-edited record. Check the raw Mongo document for the affected entry.
failed pre-migration backup for <uuid>: … failures
: The pre-migration backup couldn’t be saved, so the migration aborted before overwriting state. The nested reason points at the underlying storage issue — usually a Mongo connectivity or write-permission problem on the canonical-storage path. Re-run after fixing.
Pre-migration backup wasn’t taken : The pre-migration backup only fires when the player already has Link Cable data to overwrite. Brand-new accounts don’t get one because there’s nothing to back up.
Next Steps
Section titled “Next Steps”- Backups — managing the pre-migration backups (and any others).
- Beta and Production Rollout — post-migration network operation.
- Commands Reference — every
/linkcablesubcommand.