Results and reasons
Every status a HotCodePush sync returns, from up_to_date to skipped and failed, and every reason code with its meaning and what to do about it.
A sync resolves to one of seven statuses, and a skipped or failed status carries a reason, a code that reads as a sentence. The debug screen, the console, hotcodepush device probe and the typed result in the app print the same code for the same situation. Troubleshooting routes each one to its cause.
The statuses
| Status | Means |
|---|---|
up_to_date | There is nothing to do. release is the running release, or null on the embedded bundle. |
available | A release this device can take is not downloaded yet. checkForUpdate() answers it, and sync() when downloadStrategy is manual. |
downloaded | The update is downloaded and verified, waiting for its apply moment: next_start, next_resume, or a manual call to applyUpdate(). |
applied | The apply happened, and the update becomes the current release as the app reloads. |
nothing_to_apply | applyUpdate() found nothing waiting. |
skipped | There is a newer release and this device will not take it now, and reason says why. |
failed | Something went wrong on the way, and reason says what and message says it in words. |
release is null where no release could be evaluated. On skipped it is the newest release the device will not take, except for release_revoked, where it is the release the device falls back to. The condition field names the condition type behind device_incompatible or device_not_targeted, one of binary, fingerprint, os, attribute and device, never a value.
The result types, the methods and the events are on the API page of each SDK.
Skipped reasons
A skip means the device evaluated a newer release and decided against it, and the next check evaluates again.
| Reason | Means | What to do |
|---|---|---|
build_debug | A debug build has isEnabledInDebugBuilds off, or the build embeds no bundle, as a React Native or Expo debug build does. | Test on a release build. |
bundle_failed_before | This bundle failed on this device before and is not tried again here. | Publish a new release, or call clearUpdates() on the device. |
channel_paused | The channel is paused and serves nothing new. | Fix what the devices hit, then resume the channel: the pause. |
condition_unsupported | The release uses a condition type this SDK does not know, which fails closed. | Ship a store build with a current SDK, and release without the type until then. |
connection_metered | downloadStrategy is unmetered and the connection is metered or constrained. | Wait for Wi-Fi, or set downloadStrategy to auto. |
device_incompatible | The release does not support this binary, OS or native fingerprint, and condition says which. | Ship the store build, or widen the range: the fingerprint for fingerprint, the binary range for binary and os. |
device_not_in_rollout | The rollout has not reached this device yet. | Raise the percentage, wait for the progression, or release to the one device: the rollout. |
device_not_targeted | The release targets attributes or a device list this device does not match, and condition says which. | Set the attributes before the first sync, or release without the condition. See Target devices with attributes. |
release_older_than_binary | The release was created before this binary was built, so the build excludes it. | Create a release after the build. |
release_revoked | The running release was revoked, and the device moves to an older eligible release or the embedded bundle. | Publish a new release. |
spending_cap_reached | The organization's spending cap is reached and this device is beyond it this month. | Raise the cap, or wait for the month to turn. |
Failed reasons
A failure means the cycle could not finish, and every one retries on the next check.
| Reason | Means | What to do |
|---|---|---|
channel_unknown | The channel name set at runtime is not in the app's index of discoverable channels, or the build carries no channel, its build step having run offline or without a token, or the channel the device follows serves no index because it was deleted or has expired. The device keeps its bundle and its channel and keeps checking. | Flag the channel discoverable or switch by id, or rebuild with a token. For a channel that is gone, clear a runtime choice with setChannel(null) as Return to the build's channel shows. A recreated channel gets a new id, so only a choice by name resolves again on its own. |
content_mismatched | What was downloaded is not what the manifest promised: a file off its hash, a pack whose length is off its size, an entry past its size, a broken archive. | A persistent one is a support request with the probe's --json. |
device_offline | The index could not be fetched and no usable cached copy exists. | Do nothing, since the next check with a connection succeeds. |
download_failed | The pack or a file could not be downloaded after three attempts inside the check, one and three seconds apart, or would not fit on the device. A 404 or 410 is not retried. | Do nothing, since the next check tries again. |
index_invalid | The index is in a format newer than this SDK knows, it failed to parse, or it names another app, channel or platform. | Ship a store build with a current SDK. A persistent one on a current SDK is a support request. |
manifest_invalid | The manifest breaks the wire rules, its bytes are off the hash the index promised, it names another bundle or platform, or a URL in it points outside HotCodePush. | A persistent one is a support request with the probe's --json. |
signature_invalid | The manifest's signature did not verify against the public keys the build lists. | The release was signed with a key this build does not trust. See Sign your bundles. |
device_offline, channel_unknown and index_invalid never leave the device as an event. The other four are reported as failed events and count in the release's download and verification failures.
Rollback reasons
A rollback is not a sync result: it arrives on the updateRolledBack event, on notifyReady()'s rollbackReason, and in the device's failed event for the release.
| Reason | Means | What to do |
|---|---|---|
app_crashed | A start found the release's pending marker still set, so the previous run never reached readiness. | The bundle crashes at start on this device, and auto-pause stops a release that does it on enough devices. |
app_requested | The app called rollbackUpdate(), with its own reason carried as the event's detail. | What the app detected is in its reason text. |
readiness_timed_out | The release did not signal readiness within readyTimeoutSeconds, 10 by default: no first render, or no notifyReady() under readySignal: manual. | The bundle is broken on this device, or the app renders late. The release's counters say which, and Roll back a release covers the fleet. |
After every rollback the device marks the bundle as failed on itself, which is what bundle_failed_before reports from then on.
What the device reports
A device reports each release it saw once, as event rows. A checked row carries available or skipped with the reason, and an applied row says the device started the release.
A confirmed row says the release passed the readiness gate, and a failed row carries its reason, a rollback among them. An up_to_date or a failed check reports nothing.
The console's device page and npx hotcodepush device get --device <id> list the rows, and npx hotcodepush release get prints the release's counters: applied, confirmed and failed by reason.
| Rows | Means |
|---|---|
checked available, applied, confirmed | The device took the release, started it and passed the readiness gate: the update landed. |
checked available, applied, failed readiness_timed_out or app_crashed | The device started the release and rolled back, and the bundle is on its blocklist now. |
checked available, nothing after | The update is downloaded and waiting for its apply moment, still downloading, or the app holds restarts. The debug screen's Downloaded line settles it. |
checked available, failed download_failed or signature_invalid | The download or its verification failed before any start, and the device retries on its next check. |
checked skipped with a reason, nothing after | The device evaluated the release and will not take it. The reason's row above says what to do. |
| no row at all | The device has not checked since the release went live, follows another channel, or can download updates but cannot report back. |
A missing row is not evidence that the device did not update. A device that cannot report back updates normally, and the debug screen and the probe still work for it. The rows live as long as the release's bundle, the device's record 90 days after its last report. See Privacy and device data.
Last updated on
Troubleshooting
Find why a device did not take a release, with the debug screen and the device probe, the eight common causes and their fix, and the rarer ones as one table.
FAQ
Short answers about HotCodePush, from supported frameworks and store rules to privacy, pricing and migration, each pointing to the page that owns the details.