---
title: "Read device logs"
description: "How to read Shorebird's updater logs on Android, iOS, macOS, Windows and Linux, and what each line means when a patch doesn't arrive."
---

When a patch doesn’t reach a device, or reaches it and doesn’t run, the device’s logs usually say why. The Shorebird updater writes a line for every patch check, download and install. This page shows how to read those logs on a release build, with no debugger attached, and what the lines mean.

## Get the logs

Start reading the logs first, then start the app. The updater checks for patches once each time the app’s process starts, so fully close the app before each attempt.

* Android

  Connect the device over USB (or start the emulator) and run:

  ```
  adb logcat -c
  adb logcat -s flutter
  ```

  The first command clears old output. The second shows only the `flutter` tag, which is where the updater and Shorebird’s Flutter engine write. To close the app completely before a new attempt, run `adb shell am force-stop <your.package.name>`.

* iOS

  1. Connect the device to a Mac and open the **Console** app.
  2. Select the device in the sidebar and click **Start**.
  3. Type `shorebird` in the search field and press Return.
  4. Start the app on the device.

  The updater’s lines contain `[shorebird]`, and the engine’s lines contain `Shorebird`, so this search finds both. To keep other apps’ lines out, also filter on your app’s process, which for a Flutter app is `Runner` unless you renamed it.

* macOS

  Open the **Console** app on the Mac running your app, click **Start**, type `shorebird` in the search field, and press Return. Then start the app. Console shows the updater’s lines, the ones containing `[shorebird]`.

  The engine’s lines, such as `Shorebird updater: no active patch.`, don’t reach Console on macOS. To see them, start the app from Terminal by running the executable inside its bundle, for example `/Applications/MyApp.app/Contents/MacOS/MyApp`. Those lines print in Terminal.

* Windows and Linux

  Start the app from a terminal. The updater writes its lines to that terminal.

If no lines mention Shorebird at all, the app wasn’t built with `shorebird release` and can’t receive patches; see [Patch not showing up](/code-push/troubleshooting/#patch-not-showing-up).

## What a working update looks like

On the launch after you publish a patch, the log has lines like these, with other lines in between. This is Android, with long values shortened to `...`:

```
Shorebird updater: no active patch.
Starting Shorebird update
[shorebird] Sending patch check request: app_id: <your app ID>, channel: stable, release_version: 1.0.0+1, platform: android, arch: aarch64, current_patch_number: None
[shorebird] Patch check response: PatchCheckResponse { patch_available: true, patch: Some(Patch { number: 1, ... }), rolled_back_patch_numbers: Some([]) }
[shorebird] Downloading patch 1 for app <your app ID> (version 1.0.0+1)
[shorebird] Patch 1 successfully downloaded. It will be launched when the app next restarts.
[shorebird] Update thread finished with status: Update installed
```

On the next launch, the app runs the patch, and the first line names the patch it loads instead:

```
Shorebird updater: active path: ...
```

How to read the patch check request line, including the formats older engines print, is in [Patch not showing up](/code-push/troubleshooting/#patch-not-showing-up).

## What the lines mean

The lines below are from releases built with Flutter 3.47.9. Where an older Flutter version prints something different, the section says so.

### The update check finished

```
[shorebird] Update thread finished with status: <status>
```

This is the last line of every automatic check.

| Status                                                               | Meaning                                                                                                                                                      |
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `No update`                                                          | The track has no patch for this release that the device doesn’t already have.                                                                                |
| `Update installed`                                                   | A patch downloaded and installed. It runs on the next launch.                                                                                                |
| `Update had error`                                                   | The check, download or install failed. An earlier line starting with `Update failed:`, and any `Caused by:` lines after it, say why; see the sections below. |
| `Update available but previously failed to install. Not installing.` | The newest patch is one this device has marked bad. See [The device skips a patch that failed before](#the-device-skips-a-patch-that-failed-before).         |
| `Update already in progress`                                         | An `update()` call from your code was already running when this check started. That update carries on.                                                       |

### The patch check says what’s available

```
[shorebird] Patch check response: PatchCheckResponse { patch_available: false, patch: None, rolled_back_patch_numbers: Some([2]) }
```

`patch_available` and `patch` say whether the track has a patch for this release, and which one. `rolled_back_patch_numbers` lists the release’s [rolled back](/code-push/rollback/) patches; the device removes any of them it has. If you expected a patch and `patch_available` is `false`, check that the patch is on the track the device asked for (`channel` in the request line) and that it wasn’t rolled back.

### A patch downloaded

```
[shorebird] Patch 1 successfully downloaded. It will be launched when the app next restarts.
```

The patch is installed on the device and runs from the next launch. Nothing else needs to happen. To run it sooner, see [Restarting after an update](/code-push/update-strategies/#restarting-after-an-update).

### The device skips a patch that failed before

```
[shorebird] Patch 2 is known bad, skipping.
```

On releases built with Flutter before 3.41.9, the line is `Patch 2 has previously failed to boot, skipping.`

This device has marked patch 2 bad, so it won’t install it again. A patch is marked bad when it fails to load, including when the app’s process ends while the engine is still loading it, and, on Flutter 3.41.9 and newer, when its download fails the checks described in [The downloaded patch doesn’t match the release](#the-downloaded-patch-doesnt-match-the-release). The device keeps running its previous patch, or the release.

**What to do:** [roll back](/code-push/rollback/) patch 2 so devices that haven’t tried it yet don’t download it, fix the problem, and publish a new patch. Devices install the new patch number as usual. If the patch crashed an iOS app, see [App crashes after a patch installs](/code-push/troubleshooting/#app-crashes-after-a-patch-installs).

### A patch failed to load

```
[shorebird] Reporting failed launch.
```

The engine couldn’t load the patch this launch was meant to run, and the device marks the patch bad so it won’t try it again. What the app runs on that launch and later ones depends on the platform and the Flutter version; see [Patch integrity and automatic rollback](/code-push/rollback/#patch-integrity-and-automatic-rollback).

### The downloaded patch doesn’t match the release

```
[shorebird] Update failed: This app reports version 1.0.7+8, but the binary is different from the version 1.0.7+8 that was submitted to Shorebird.
```

A few lines further on, under `Caused by:`, is `Update rejected: hash mismatch.` The patch downloaded, but applying it to the app on this device didn’t produce the code Shorebird built, because the app on the device isn’t the build `shorebird release` uploaded. See [Patches can’t install because the app isn’t the build Shorebird released](/code-push/troubleshooting/#patches-cant-install-because-the-app-isnt-the-build-shorebird-released).

### The device couldn’t reach Shorebird

```
[shorebird] Update failed: Network request failed; the server could not be reached.
```

On releases built with Flutter before 3.47.7, the line is `Update failed: Patch check request failed due to network error. Please check your internet connection.`

The device is offline, or its network blocks Shorebird. The updater tries again on the next launch, and the device keeps the patch it has.

On releases built with Flutter 3.47.9 and newer, a `Caused by:` line after it gives the cause. On Android, iOS and macOS, `TLS handshake failed` there means the connection was made but the certificate it got wasn’t trusted; on Windows and Linux, the same problem shows as a certificate error. That usually means a proxy or security product on the network inspects HTTPS traffic. These releases trust the same certificates as the rest of the device: on Android, the ones your app’s network security configuration allows; on iOS and macOS, the ones the system trusts, including roots installed by device management; and on Windows and Linux, the operating system’s trusted certificates. Ask the network’s administrators to let Shorebird’s traffic through, or have the device trust the proxy’s root certificate.

### The patch check was refused

```
[shorebird] Update failed: Request failed with status: 403
```

Shorebird refused the patch check. The usual cause is that your organization reached its patch install limit; see [Your organization reached its patch install limit](/code-push/troubleshooting/#your-organization-reached-its-patch-install-limit).

### The app is running the release’s own code

```
Shorebird updater: no active patch.
```

The device has no installed patch, so it runs the release. That’s expected until a patch has downloaded. If a patch should have arrived by now, compare the `release_version` in the patch check request with the release you patched; see [Patch not showing up](/code-push/troubleshooting/#patch-not-showing-up).

### The automatic check is turned off

```
Shorebird auto_update disabled, not checking for updates.
```

`shorebird.yaml` has [`auto_update: false`](/code-push/shorebird-yaml/#auto_update), so the app checks only when your code calls `package:shorebird_code_push`. See [How devices get patches](/code-push/how-devices-get-patches/#turning-off-the-automatic-check).
