Skip to main content

Security — Error Codes

UpdateErrorCode is the canonical enum the plugin throws for every typed failure across all four feature areas. Errors come back as UpdateError objects:

interface UpdateError {
code: UpdateErrorCode;
message: string;
details?: unknown;
}

You catch them like any other promise rejection:

import { NativeUpdate, UpdateErrorCode } from 'native-update';

try {
await NativeUpdate.sync();
} catch (e) {
const err = e as { code: UpdateErrorCode; message: string };
switch (err.code) {
case UpdateErrorCode.NETWORK_ERROR:
retryLater();
break;
case UpdateErrorCode.SIGNATURE_ERROR:
reportToSentry(err);
break;
default:
logUnknown(err);
}
}

Network errors

CodeWire valueWhenRemediation
NETWORK_ERROR'NETWORK_ERROR'DNS failure, no internet, captive portal, TLS handshake failureRetry with exponential backoff. Fail open to "no update available" — do not block the user.
SERVER_ERROR'SERVER_ERROR'Update server returned 5xxRetry; alert your monitoring on persistent 5xx.
TIMEOUT_ERROR'TIMEOUT_ERROR'Default timeout exceededIncrease downloadTimeout in PluginInitConfig or move to BACKGROUND strategy so a long download does not block the foreground.

Download errors

CodeWire valueWhenRemediation
DOWNLOAD_ERROR'DOWNLOAD_ERROR'Generic download failure (TLS aborted, premature close, content-length mismatch)Retry; if persistent, check server logs for connection-level issues.
STORAGE_ERROR'STORAGE_ERROR'Cannot write to the app sandbox (full disk, permission revoked)Call delete() to free old bundles; surface a "low storage" UI to the user.
SIZE_LIMIT_EXCEEDED'SIZE_LIMIT_EXCEEDED'Bundle exceeds maxBundleSize config or platform-imposed cellular capSlim the bundle; raise maxBundleSize only if you have validated the bundle is honestly that large.

Security errors

These are the codes you should treat as alerts — they often indicate either misconfiguration or active tampering attempts.

CodeWire valueWhenRemediation
VERIFICATION_ERROR'VERIFICATION_ERROR'Umbrella — verification failed but the SDK could not pinpoint which stepInspect error.details for the specific step.
CHECKSUM_ERROR'CHECKSUM_ERROR'Computed checksum did not match expectedThe bundle was modified after signing. Re-sign and re-upload. Investigate intermediate caches / proxies.
SIGNATURE_ERROR'SIGNATURE_ERROR'Public key did not verify the signature over the checksumConfirm the public key in LiveUpdateConfig.publicKey matches the private key used by the CLI bundle sign step.
INSECURE_URL'INSECURE_URL'HTTP (not HTTPS) URL passed to a download methodUse HTTPS. iOS App Transport Security would block plain HTTP anyway.
INVALID_CERTIFICATE'INVALID_CERTIFICATE'TLS certificate failed pinning check or chain validationRenew + re-pin. See Certificate pinning.
PATH_TRAVERSAL'PATH_TRAVERSAL'Bundle ZIP contained an entry that resolves outside the install directory (e.g. ../../etc/passwd)Treat as adversarial — alert your monitoring. The bundle is rejected before any byte is written.

Installation errors

CodeWire valueWhenRemediation
INSTALL_ERROR'INSTALL_ERROR'Could not write the bundle into place after download (filesystem race, atomic-rename failure)Retry. If persistent, file an issue with error.details.
ROLLBACK_ERROR'ROLLBACK_ERROR'Rollback to the previous bundle failedRare. Usually requires a binary reinstall from the App Store / Play Store to recover. Surface a "Please reinstall the app" dialog.
VERSION_MISMATCH'VERSION_MISMATCH'Bundle's declared version did not match the version field returned by the serverThe server lied or your build step is out of sync. Check your CI signing flow.

Permission errors

CodeWire valueWhenRemediation
PERMISSION_DENIED'PERMISSION_DENIED'OS denied a required permission (notifications, exact alarms, etc.)Inspect error.details for which permission. Render a rationale UI before re-prompting.

App-update errors (App Store / Play Store flows)

CodeWire valueWhenRemediation
UPDATE_NOT_AVAILABLE'UPDATE_NOT_AVAILABLE'Calling complete / immediate before a download existsAlways gate behind getAppUpdateInfo() + appUpdateReady event.
UPDATE_IN_PROGRESS'UPDATE_IN_PROGRESS'Triggering a second flow before the first completesInspect info.installStatus; wait for INSTALLED / FAILED.
UPDATE_CANCELLED'UPDATE_CANCELLED'User declined the Play promptSurface a non-blocking banner; respect their choice for the session.
PLATFORM_NOT_SUPPORTED'PLATFORM_NOT_SUPPORTED'Calling Android-only methods on iOS / web; calling a method on Huawei without GMSBranch on Capacitor.getPlatform() and feature-detect via getAppUpdateInfo() flags.

App-review errors

CodeWire valueWhenRemediation
REVIEW_NOT_SUPPORTED'REVIEW_NOT_SUPPORTED'Play Services missing (Huawei, F-Droid, no-GMS Android), iOS without StoreKit, web without webReviewUrlFall back to opening webReviewUrl in a browser.
QUOTA_EXCEEDED'QUOTA_EXCEEDED'Some platforms surface this when their internal cap is exhaustedSkip silently; quota resets eventually.
CONDITIONS_NOT_MET'CONDITIONS_NOT_MET'Plugin-side throttle blocked the call (minimumDaysSinceInstall, etc.)Skip silently; respect the throttle.

Configuration errors

CodeWire valueWhenRemediation
INVALID_CONFIG'INVALID_CONFIG'Required field missing in any config block, or value out of rangeInspect error.message — it identifies the offending field.
NOT_CONFIGURED'NOT_CONFIGURED'Method called before initialize() resolvedAwait initialize() before any other call. Use the isInitialized() check in defensive code.

Catch-all

CodeWire valueWhenRemediation
UNKNOWN_ERROR'UNKNOWN_ERROR'A failure the SDK could not classify into one of the codes aboveTreat as a bug — log error.details and file an issue.

Mapping to Error classes (power users)

The plugin also exports concrete error classes for instanceof checks:

import {
NativeUpdateError, // base class
ConfigurationError, // INVALID_CONFIG, NOT_CONFIGURED
DownloadError, // DOWNLOAD_ERROR, NETWORK_ERROR, TIMEOUT_ERROR, STORAGE_ERROR
ValidationError, // CHECKSUM_ERROR, SIGNATURE_ERROR, VERIFICATION_ERROR, PATH_TRAVERSAL, VERSION_MISMATCH
StorageError, // STORAGE_ERROR, SIZE_LIMIT_EXCEEDED
UpdateErrorClass, // alias for the base class kept for backwards compat
} from 'native-update';

try {
await NativeUpdate.sync();
} catch (e) {
if (e instanceof ValidationError) {
// signature / checksum / path-traversal — alert
} else if (e instanceof DownloadError) {
// network — retry
}
}

Both styles work — the code field is always populated even on instances of the typed classes.


Error code catalogue verified against src/definitions.ts in the plugin repo as of 2026-05-11. Documented by Ahsan Mahmood.