Sync Status Reference
The SDK reports detailed status updates via the statusCallback. This page documents all status values and their meanings.
Status Values
UP_TO_DATE
The application is running the latest version.
case SyncStatus.UP_TO_DATE:
console.log('App is up to date');
break;When triggered:
- After checking for updates when no update is available
- When current version matches or exceeds server version
UPDATE_INSTALLED
An update has been downloaded, unzipped, and installed. The update will activate on next app restart.
case SyncStatus.UPDATE_INSTALLED:
console.log(`Update ${data?.version} installed!`);
console.log('Restart to apply');
break;Data properties:
version: Update version numberbuildNumber: Update build number
UPDATE_IGNORED
An available update was skipped.
case SyncStatus.UPDATE_IGNORED:
console.log('Update skipped:', data?.compatibilityReason);
break;When triggered:
- Update requires store update and
allowStoreUpdateOverrideis false - User declined update in manual flow
Data properties:
message: Reason for skippingcompatibilityReason: Detailed incompatibility reason
ERROR
An error occurred during the sync operation.
case SyncStatus.ERROR:
console.error('Sync error:', data?.message);
break;When triggered:
- Network request failed
- Download failed
- Unzip failed
- Install failed
Data properties:
message: Error message or descriptionupdateAvailable: Alwaysfalseon error
SKIPPING_BECAUSE_HMR_ENABLED
Hot Module Replacement is active, so OTA sync is skipped.
case SyncStatus.SKIPPING_BECAUSE_HMR_ENABLED:
console.log('OTA skipped - development mode');
break;When triggered:
- HMR is enabled (typically during development)
- User didn’t explicitly override this behavior
IN_PROGRESS
A sync operation is already in progress.
case SyncStatus.IN_PROGRESS:
console.log('Sync already running');
break;When triggered:
sync()called while another sync is running- The concurrent call receives the in-flight result, so only one download and install happens
CHECKING_FOR_UPDATE
Intermediate status. The SDK is checking the server for updates.
case SyncStatus.CHECKING_FOR_UPDATE:
showSpinner('Checking for updates...');
break;AWAITING_USER_ACTION
Intermediate status. Waiting for user to respond to update prompt.
case SyncStatus.AWAITING_USER_ACTION:
// User dialog is shown
break;When triggered:
- Manual update flow with user confirmation
promptToRestartAfterInstalldialog is shown
DOWNLOADING_PACKAGE
Intermediate status. The update package is being downloaded.
case SyncStatus.DOWNLOADING_PACKAGE:
showSpinner('Downloading update...');
break;Use downloadProgressCallback for progress percentage.
INSTALLING_UPDATE
Intermediate status. The update package is being installed.
case SyncStatus.INSTALLING_UPDATE:
showSpinner('Installing update...');
break;This includes unzipping into a temporary directory and renaming it into place.
RELOADING_APP
Intermediate status. The JavaScript runtime is being recreated to load the installed update in the current process.
case SyncStatus.RELOADING_APP:
showSpinner('Reloading...');
break;RELOAD_FAILED
The installed update could not be loaded through the native soft reboot API. The runtime is older than 9.1.0, or the native loader rejected the reload.
case SyncStatus.RELOAD_FAILED:
console.warn('Soft reboot unavailable:', data?.message);
break;Unless fallbackToProcessRestart is false, the SDK falls back to a process restart after reporting this.
ROLLED_BACK
The update that this process launched failed before it displayed any content. It has been quarantined, and the app is being relaunched into the newest known-good bundle: a newer update if one is available, otherwise the previous update, otherwise the store bundle.
case SyncStatus.ROLLED_BACK:
console.warn('Update rolled back:', data?.updateId, data?.message);
break;Data properties:
updateId: Id of the update that failedversion,buildNumber: What the failed update reportedmessage: The error that was observedupdateAvailable: Alwaysfalse
The callback fires before the relaunch, so keep any work here synchronous and short. The quarantined update is not offered or installed again on this binary. See Launch Safety.
Complete Example
import { initNorrix, SyncStatus } from '@norrix/client-sdk';
initNorrix({
updateUrl: 'https://norrix.net',
checkForUpdatesOnLaunch: true,
installUpdatesAutomatically: true,
statusCallback: (status, data) => {
switch (status) {
// Progress states
case SyncStatus.CHECKING_FOR_UPDATE:
console.log('Checking for updates...');
break;
case SyncStatus.DOWNLOADING_PACKAGE:
console.log('Downloading update...');
break;
case SyncStatus.INSTALLING_UPDATE:
console.log('Installing update...');
break;
case SyncStatus.AWAITING_USER_ACTION:
console.log('Waiting for user...');
break;
// Final states
case SyncStatus.UP_TO_DATE:
console.log('App is up to date');
break;
case SyncStatus.UPDATE_INSTALLED:
console.log(`Update ${data?.version} installed!`);
console.log('Build:', data?.buildNumber);
break;
case SyncStatus.UPDATE_IGNORED:
console.log('Update skipped');
if (data?.compatibilityReason) {
console.log('Reason:', data.compatibilityReason);
}
break;
// Error states
case SyncStatus.ERROR:
console.error('Sync error:', data?.message);
break;
case SyncStatus.IN_PROGRESS:
console.log('Sync already in progress');
break;
case SyncStatus.ROLLED_BACK:
console.warn('Update rolled back:', data?.updateId);
break;
case SyncStatus.SKIPPING_BECAUSE_HMR_ENABLED:
console.log('Skipping - HMR enabled');
break;
}
},
});Status Flow Diagram
checkForUpdates()
│
▼
CHECKING_FOR_UPDATE
│
├─── No update ──────► UP_TO_DATE
│
├─── Store required ─► UPDATE_IGNORED
│
▼
DOWNLOADING_PACKAGE
│
▼
INSTALLING_UPDATE
│
├─── Success ────────► UPDATE_INSTALLED
│
└─── Failure ────────► ERRORROLLED_BACK is not part of this flow. It is reported at launch, when the update this process booted failed before displaying content:
launch on update
│
├─── content displayed ──► (nothing reported)
│
└─── error first ────────► ROLLED_BACK ──► relaunch into the newest known-good bundle