Troubleshooting
Symptoms in the order people meet them, with the cause and the fix — save, load, values, autosave, cloud and the Editor.
The save never appears#
| Symptom | Likely cause | Fix |
|---|---|---|
SaveAsync succeeds but no file exists | You are looking in the wrong root | Open Save Folder, or read the path from the smoke test's report |
NF.PERSIST.STORAGE.PATH_TOO_LONG | Namespace + environment + slot exceeded the path budget | Shorten the namespace, or raise Storage.MaxPathLength deliberately |
| Nothing is written and no error appears | Persistence was never initialised | Call Initialize during startup; a save before that is NF.PERSIST.LIFECYCLE.NOT_INITIALIZED |
| The storage probe fails in the Editor | Permissions, a read-only volume, or another process holding the file | Check free space and folder permissions; the probe names the root |
Loading fails#
| Code | Meaning | Fix |
|---|---|---|
NF.PERSIST.SLOT.NOT_FOUND | The slot was never written | Treat LoadOutcome.NotFound as "new game", not as an error |
NF.PERSIST.SECURITY.AUTHENTICATION_FAILED | The file was altered, or the key does not match | Check the key provider and Security.KeyId; nothing was read or decrypted |
NF.PERSIST.SECURITY.KEY_UNAVAILABLE | Encryption is configured but no key was supplied | Register an ISaveKeyProvider, or turn encryption off |
NF.PERSIST.ENVELOPE.INTEGRITY_MISMATCH | The file is damaged | Use recovery: it quarantines the damaged file and restores the newest valid backup |
NF.PERSIST.MIGRATION.PATH_MISSING | A migration step is missing for a schema in the save | Register the step, and declare the versions so validation catches it earlier |
NF.PERSIST.SERIALIZATION.MALFORMED | The document does not match the model | Usually a model change without a migration, or a member the type cannot represent |
A failed load never modifies the slot. Recovery is a separate, explicit step.
"My values changed after a round trip"#
| Symptom | Cause | Fix |
|---|---|---|
| Dates come back as a different instant | Almost always a model type that cannot represent the value | Inspect the written document; the framework writes timestamps in round-trip, culture-independent form |
| Large integers lose precision | A double in your model, or a serialisation path outside the framework | Keep 64-bit counters as long; the framework preserves them exactly |
| Unknown fields disappeared | The document was re-serialised outside the framework, or a schema change deleted them | Use the framework's save path; PreserveAndReport keeps unknown members across a load/edit/save cycle |
Autosave#
| Symptom | Cause | Fix |
|---|---|---|
| No autosave happens | Autosave.Enabled is false, or nothing called MarkDirty | Enable it, and mark dirty on real change events |
| Autosave happens too often | Debounce is short and the game marks dirty every frame | Increase the debounce, or mark dirty on milestones rather than continuously |
| A save is lost when the app is suspended | Nothing flushed on pause | Set Autosave.SaveOnPauseRequested, or call MarkDirty from your pause handler |
| Frame hitches on large saves | Projection plus serialisation run on the caller's thread by default | Consider Storage.OffloadWritesToThreadPool, and measure with the Performance test category |
Cloud#
| Symptom | Cause | Fix |
|---|---|---|
| "Cloud is enabled but no provider is installed" | The setting is on but no transport was supplied | Implement ICloudTransport and pass it to CloudSaveSyncService; the package ships no service |
| Repeated conflicts on one device | The provider reports no conditional-write support, or is rewriting metadata | Declare capabilities truthfully — see Providers and adapters |
| Uploads never happen offline | OfflineQueueEnabled is off, or the journal cannot be written | Turn the queue on; check the save root is writable |
| A conflict lost a version | PreserveConflictCopies is off | Turn it on: the losing copy is preserved in a *_conflict_<rev> slot |
"Everything looks fine but the Editor complains"#
The validation report distinguishes four kinds of finding, and only two of them are problems: WARNING and ERROR are actionable and each carries a remedy; INFO is worth knowing; NOT VERIFIED means nothing was run for this combination — it is not a failure and not a promise. See Validation.
Getting help#
Run NexusForge → Persistence → Validate Everything first: its output is exactly what a maintainer needs, and it is safe to paste because it contains no payload bytes, keys or credentials. Support lists the rest.
Next#
- Error codes — the complete reference.
- Recovery — what to do about a damaged save.
- FAQ — the questions that are not symptoms.
Something wrong on this page? Every page here describes behaviour that is checked in the repository. If a page and the package disagree, the package wins.
Report a documentation problem · Frequently asked questions · Troubleshooting