Troubleshooting
This page covers the most common issues with Shorebird Code Push. Still stuck? Reach out on Discord or file an issue. The Shorebird team is happy to help.
Find your symptom below, or search the page for the exact message you see.
A patch didn’t reach devices
- Patch not showing up
- Patches stopped installing on devices
- Patches can’t install because the app isn’t the build Shorebird released
- Patch check fails with
Request failed with status: 500 - Your iOS build number is auto incrementing
shorebird patch warned or stopped
Your app contains asset changeswarningYour app contains native changeswarning- Patch stops in CI with
Not publishing(exit code 70) shorebird patchcan’t find a release to patch- Patching an obfuscated iOS release built with older Flutter
- Message saying patch might run slowly
- Sending a patch-debug.zip to Shorebird
- Patch download size is unexpectedly large
A build, release or install failed
shorebird releasesays the release already existsAborting due to validation errors- Shorebird fails to install
- Can’t run your app in VS Code
- Could not find an option named “dart define”
- Xcode project
overrides FLUTTER_ build setting(s)warning - iOS app extension versions don’t match the app
- Invalid Podfile file
- Missing a provisioning profile or no signing team was found
shorebird previewcan’t install an iOS release- Unsupported class file major version 65
- Android build fails with “lower than Flutter’s minimum supported version”
libapp.so.sym or libapp.so.dbg not presentwarning on Android- Resolving persistent compile or build failures
The app crashed after a patch
Sign-in, CI credentials or network
- Sign-in and credential errors
- Shorebird commands fail with network/TLS connection errors behind a proxy
- GitHub Actions sign-in errors
Patch not showing up
Section titled “Patch not showing up”Your first step in debugging should be to check your app’s logs. See Read device logs for how to get them and what each line means.
You should see logs prefixed with [shorebird]. If you do not see [shorebird]
in your logs, the app you are running was not built using shorebird release
and cannot receive patches. You will need to redistribute your app using a
binary created by shorebird release.
If you do see Shorebird in your logs, you’ll want to look for a line that includes the patch check request being made. It looks like:
release_version is the release version your app is running, and
current_patch_number is the patch it is currently running (None if it is
running the release unpatched).
Older engines print this line in a different format, for example:
Depending on the engine version, the older format may leave out client_id or
current_patch_number. It always includes release_version.
If the release version is the version you expect to see, check the Shorebird Console to ensure that this release exists for the given app ID and that it has a patch. Please reach out on Discord if such a patch exists and is not being applied.
Common issues:
Patches were installing and then stopped.
See Patches stopped installing on devices.
The app is running in Debug or Profile mode.
Shorebird only runs in release builds. Test patches with a build from
shorebird release or shorebird preview, not flutter run. See
Does Shorebird work in debug or profile mode?
You are testing on an iOS Simulator.
iOS patches only install on physical devices; Android emulators work. See Does Shorebird work on iOS Simulators?
The patch was created for a different release version than the one running on your device/emulator.
Patches are only compatible with the release version they were created for. If
you create a patch for version 1.0.0+1, it will not work on version 1.0.0+2.
How to tell if this is the problem
You will see Shorebird updater: no active patch in your device logs.
How to fix it
Ensure that the version of your app on your device/emulator matches the version of the release you patched. You can see what release version your app is running by looking in the device logs for a patch check request:
Only patches created for this release version will be compatible with your app.
The app’s process is still running because of a foreground service.
If the app runs a foreground service or other long-running background work, swiping it from the recent-apps list does not kill the process. Shorebird loads the patch on the next process start.
How to tell if this is the problem
The process ID does not change when you swipe the app away. Run
adb shell pidof <your.package.name> before and after swiping: if it prints the
same PID both times, the process never died and no patch will be applied.
From Dart, the equivalent signal is checkForUpdate() returning
UpdateStatus.restartRequired, or readNextPatch() reporting a higher patch
number than readCurrentPatch().
How to fix it
Force-stop the app, or stop the service first, then relaunch. See How do you use Shorebird with a long-running Android background process?.
Patches stopped installing on devices
Section titled “Patches stopped installing on devices”Patches were reaching your users, and now new patches don’t install. Devices keep running the patch they already have. Check these causes in order.
Your organization reached its patch install limit
Section titled “Your organization reached its patch install limit”Once the apps on your plan have used every patch install the plan allows this billing period, Shorebird refuses patch checks from those apps. New patches stop installing until the limit goes up or the limit resets.
How to tell if this is the problem
-
The device logs show the patch check failing with:
-
The Shorebird Console shows a banner that says “Patches are not being delivered.”, or “Your last payment didn’t go through.” if a payment failed.
shorebird releaseandshorebird patch(1.6.135 and newer) print a warning that starts withPatches are not being delivered:. -
Members of the organization get an email when usage reaches 80% of the limit, and another when it reaches the limit, unless they’ve turned these emails off.
How to fix it
The banner says which limit was reached. On an Enterprise plan, email billing to raise the limit. Otherwise the organization owner fixes it from the Plan page:
- If the plan’s included installs are used up and the banner says overages are turned off, turn on overages or upgrade the plan. Otherwise, upgrade the plan.
- If overages are on and you’ve reached your spending limit (the banner calls it the overage limit), raise the limit.
- If a payment failed, update the payment method. See Failed payments.
Devices pick up patches on their next patch check after the upgrade, the limit change, or the plan’s payment going through. After you pay an annual plan’s overage invoice, patches start installing again within the hour. If you change nothing, patches start installing again within the hour after the next billing period starts (for an annual plan’s overage limit, the next month).
The app in the store isn’t the build Shorebird released
Section titled “The app in the store isn’t the build Shorebird released”If patches install on some builds but not on the one in the store, see Patches can’t install because the app isn’t the build Shorebird released.
Patches can’t install because the app isn’t the build Shorebird released
Section titled “Patches can’t install because the app isn’t the build Shorebird released”Every patch is made against the build shorebird release uploaded. If the app
installed on a device is a different build of the same version, no patch to that
release can install on it.
How to tell if this is the problem
The device logs show a patch failing with a message like:
Common causes
- The build in the store was made with Shorebird’s Flutter some other way than
shorebird release, such as archiving in Xcode or running Gradle aftershorebird releaseran, which leaves the project set to use Shorebird’s Flutter. A build made with the standard Flutter’sflutter builddoesn’t include Shorebird, so it never reports this. shorebird releaseran again for the same version, after an earlier run stopped partway or after the release was deleted, and the build from the earlier run was published. Shorebird keeps only the build from the last run.- On iOS, the archive was uploaded with Xcode’s Distribute App flow with Manage Version and Build Number checked. Xcode then rewrites the build number in the uploaded app, so the build in the store doesn’t match the one Shorebird recorded for the release. Uncheck it when you upload; see Uploading from Xcode. An ExportOptions.plist can do the same; see Your iOS build number is auto incrementing.
How to fix it
Publish the build shorebird release made, or release a new version with
shorebird release and publish that build. Patches made for the new version
install on devices that update to it.
If only a few devices report this, they may be running a modified copy of your app, and no change is needed.
Patch check fails with Request failed with status: 500
Section titled “Patch check fails with Request failed with status: 500”The device logs show the patch check failing with:
If your app calls update() from
package:shorebird_code_push, it
throws an UpdateException with the same message.
A 500 status means Shorebird’s server failed to answer the patch check. It isn’t
caused by your app or your patch, and there is nothing to change in either.
Devices keep running the code they already have, whether that’s the release or
an earlier patch, and check again on their next launch, or the next time your
app calls update(). Once the server answers again, they download the latest
patch as usual.
If patch checks keep failing, reach out on Discord or at contact@shorebird.dev with your app ID and the release version from the log.
App crashes after a patch installs
Section titled “App crashes after a patch installs”Your iOS app runs fine as released, but once a patch installs it crashes at
launch or soon after. If the release was built with Flutter 3.44 before 3.44.9
at revision 0cae2fc0a4, including an early 3.44.9 build at revision
c2515c46c7, the crash is in that Flutter version, and no patch can fix it.
Roll back every iOS patch on the release, then publish a new store release built
with a newer Flutter.
How to tell if this is the problem
-
The crash happens only on iOS, starts after a patch installs, and stops once every patch on the release is rolled back.
-
Crash reports from Xcode or Crashlytics show one of these:
InstructionsTable::SetCodeAt, while the patch loads at startup, before any of your Dart code runs.SimpleHashMap::LookupwithDRT_SwitchableCallMissfurther down, when execution returns into patched code, most often where anawaitresumes.
The crash can also show up as an abort where a failed null check would normally throw a Dart error.
-
The release was built with an affected Flutter revision. Check the revision, not only the version, with
shorebird releases info:In the Shorebird Console, the release’s page shows the version and the first 10 characters of the revision under the release’s name, and a “Known crashes on iOS.” alert on an affected release. The release list also shows an error sign next to each affected release.
A crash with the InstructionsTable::SetCodeAt signature has also been reported
on 3.44.9 at 0cae2fc0a4, and didn’t happen with the same app on Flutter 3.47.
If you see it there, publish a new release with the Flutter version the current
Shorebird ships.
Shorebird 1.6.135 and newer warn when you patch an affected iOS release. The warning starts with:
and, after a description of the crashes, ends with:
The patch is still created.
How to fix it
- Roll back every patch on the affected iOS release. Rolling back only the newest patch moves devices to the previous patch, which can crash the same way.
- Run
shorebird upgrade, then publish a new store release. By default,shorebird releasebuilds with the Flutter version the installed Shorebird ships, so an older Shorebird can build on an affected revision again. If you pass--flutter-version(includingfvmorsystem), update that too. Before submitting to the store, check withshorebird releases infothat the new release isn’t on an affected revision. - Patch the new release. Until users update from the store, a patch to the old iOS release can crash their app.
Why a better patch can’t fix it
A patch replaces your Dart code, but it runs on the Flutter engine inside the store build, and Shorebird builds every patch with the Flutter version its release was built with. The crash is in that engine, so only a new release built with a fixed Flutter version removes it.
Not every crash after a patch is this one. If the app still crashes with every
patch rolled back, the crash is in the release, not the patch. If it crashes
only with a patch installed and the release isn’t on an affected revision, reach
out with the crash report and the
patch-debug.zip from that
shorebird patch run.
Deferred components fail to load after a patch installs
Section titled “Deferred components fail to load after a patch installs”Your Android app uses Flutter
deferred components. They
load as released, but once a patch installs, every loadLibrary() call for a
deferred component throws:
This happens with any patch, even one that changes no code in the deferred component.
Shorebird doesn’t support deferred components. A patch replaces your app’s whole compiled Dart program, while each deferred component was compiled with the release, so the Dart VM refuses to load it alongside the patch.
How to fix it
- Roll back every patch on the affected release. Only the release itself can load its deferred components, so rolling back only the newest patch moves devices to the previous patch, which fails the same way.
- Move the code out of deferred components and publish a new store release, then patch that release. When most of a feature’s size is in assets such as models or media, download those at runtime or with Play Asset Delivery instead, which works with Shorebird.
Your app contains asset changes warning when creating a patch
Section titled “Your app contains asset changes warning when creating a patch”The shorebird patch command will print a warning if it detects changes to
files in your compiled app that correspond to asset changes (e.g., added or
removed images, fonts, etc.). This does not always mean that your patch will not
work, but Shorebird cannot be sure that the changes are safe. A patch can’t
change assets, so an asset change reaches devices only in a new release.
An example of this warning:
So what does this mean? In this case, it means you added a new image to your app. The warning is because your patched Dart code could depend on those new assets which will not be present when the patch is applied in the wild. It can be safe to ignore this kind of warning if you’re removing an asset that is not used by your code, or your Dart code knows how to handle the asset being missing.
Also included in the above changes are the AssetManifest files. These files
change any time you add or remove an asset from your app, and are generally a
symptom rather than the cause of the warning.
The final file changed above is the MaterialIcons-Regular.otf font file, which
can happen if your app uses more or fewer icons from the Dart code. Flutter will
automatically “tree shake” your fonts, so if you don’t use an icon in your Dart
code, it will not be included in the final app. You can disable this behavior
with --no-tree-shake-icons at the risk of increasing your app size.
Changes to your app’s native code, such as .dex files on Android, are not
patchable by Shorebird and get a separate warning, covered
below.
What happens if you ignore this warning?
You can bypass this warning by passing the --allow-asset-diffs flag to the
shorebird patch command.
The consequences of ignoring this warning depend on the changes that were made. In the tree-shaking example above, if you ignore the warning, your app will render incorrectly if you use an icon that was not included in the release build. Any assets introduced in a patch will fail to load, and your app may crash if it depends on them.
If you are not sure whether your change is safe, you can stage your patch and test locally before deploying it to users. For which files count as assets, and ways to keep content changeable between store releases, see Assets in Flutter apps.
Your app contains native changes warning when creating a patch, even though you haven’t changed Swift/Objective-C/Kotlin/Java code
Section titled “Your app contains native changes warning when creating a patch, even though you haven’t changed Swift/Objective-C/Kotlin/Java code”The shorebird patch command prints a warning if it detects changes in your
compiled app that correspond to native code changes. This does not always mean
that your patch will not work, but because Shorebird cannot be sure that the
changes are safe, and because Shorebird can’t patch non-Dart code, it prints a
warning.
What the CLI compares depends on the platform:
-
Android (
shorebird patch android): the.dexfiles in your app. The warning readsYour app contains native changes, which cannot be applied with a patch. -
iOS and macOS (
shorebird patch ios,shorebird patch macos): Xcode builds aren’t byte-for-byte repeatable, so a difference in your app’s executable doesn’t produce a warning on its own. When the executable differs from the release’s, the CLI also compares yourios/Podfile.lock(ormacos/Podfile.lock) with the one used to build the release, and warns if they differ:The comparison is of the whole file, so once the executable differs, anything that changes Podfile.lock triggers the warning:
pod update, a plugin version change, an edit to yourPodfile, or a different CocoaPods version (Podfile.lock records it). Native changes that don’t touch Podfile.lock, such as edits to your own Swift or Objective-C code or to Swift Package Manager dependencies, produce no warning, and neither does anything when the release was built without a Podfile.lock. Check those yourself before patching.The release stores only a hash of its Podfile.lock, not the file, so the warning can’t show what changed. To see the difference, diff your
ios/Podfile.lock(ormacos/Podfile.lock) against the one in the commit you built the release from, for examplegit diff <release-commit> -- ios/Podfile.lock. If that shows no difference, the release was built with a Podfile.lock that was never committed, for example one regenerated bypod installin CI.
Windows, Linux, shorebird patch aar and shorebird patch ios-framework
patches don’t check for native changes, so this warning doesn’t appear there.
This can be caused by a number of things. The most common causes are:
-
A dependency/plugin you are using has changed its native code. You should use caution when publishing patches that include changes to native code from plugins. In the worst case, these changes may cause your patched app to crash.
-
(Android) A dependency/plugin produces a different output on every build. This can happen if the dependency includes a timestamp indicating when it was built, for example. This kind of change is usually safe to publish, but you should be sure this is the only reason you are seeing this warning.
-
The version and build number of the patch do not match that of the release. For example, if the release was built with version
1.0.0+1, but the patch was generated with version1.0.0+2, you might see this warning. Shorebird has implemented some safeguards to make this less likely, but it is worth verifying if you are seeing this warning and you do not know why.
What happens if you ignore this warning?
If the native code that changed does not interact with your Dart code or Flutter at all, the patch should run without issue.
If you are not sure whether your change is safe, you can stage your patch and test locally before deploying it to users.
On Android, when Java or Kotlin code changed, the warning also names the
classes, methods, and fields that each changed method’s differing instructions
reference, which usually points at the dependency that changed. It details up to
10 methods per DEX file. To print every changed method and instruction in full,
including string constants, pass --show-dex-diff to shorebird patch. This
needs Shorebird 1.6.130 or newer.
If you are sure the changes are safe, you can bypass this warning by passing the
--allow-native-diffs flag to the shorebird patch command.
Patch stops in CI with Not publishing (exit code 70)
Section titled “Patch stops in CI with Not publishing (exit code 70)”Your shorebird patch job in CI failed with exit code 70 and an error like
this. When only one kind of change is blocked, the first line starts
Not publishing: native code changed or Not publishing: assets changed, and
the hint names only that flag:
The patch build differs from the release in a way a patch can’t carry. On your
own machine, shorebird patch asks Continue anyway?. In CI there’s nobody to
answer, so the patch stops instead. The CLI treats a run as CI when stdin or
stdout isn’t a terminal, when it detects a CI environment variable such as CI
or GITHUB_ACTIONS, or when you pass --json. With --json, the same message
and hint are in the error envelope’s message and hint.
Above that error, the log says what changed:
Your app contains native changes, which cannot be applied with a patch., followed by the changed native files (not printed byshorebird patch iosorshorebird patch macos; see below). See the native changes warning for common causes.Your app contains asset changes, which will not be included in the patch., followed by the changed asset files. See the asset changes warning.- With
shorebird patch iosorshorebird patch macos,Your ios/Podfile.lock is different from the one used to build the release.(ormacos/Podfile.lock).
Shorebird 1.6.135 and newer print these as errors. Older versions print them as
warnings, end with Not publishing. (Exiting. in older releases), and exit
with the same code. They stop at the first kind of change, so a build with both
native and asset changes stops again on the assets after you pass
--allow-native-diffs. The flags are the same in every version.
Decide which way to ship the change:
- The Dart code needs the change (a new plugin, a changed native API, a new
asset): ship it in a new store release. The error prints the command, such as
shorebird release android. - The Dart code doesn’t depend on it (an unused asset removed, a dependency
that rebuilt with the same behavior): pass the flag the error names,
--allow-native-diffs,--allow-asset-diffsor both, to publish the patch without the change. Devices keep the release’s native code and assets.
If you’re not sure, publish to a staging track first and test it.
On Android, the log also lists the dependencies whose versions differ from
the release, under Dependency versions differ from the release:. A dependency
that resolved to a newer version for the patch build is a common cause of .dex
changes you didn’t make. Pin dependency versions, or turn on
Gradle dependency locking,
so the patch build resolves the same versions as the release.
With shorebird patch ios and shorebird patch macos, Xcode builds aren’t
byte-for-byte repeatable, so changed native files alone don’t stop the patch.
For native code, the CLI only stops it when Podfile.lock differs from the
release’s. Asset changes still stop it, and are checked first: if both changed,
the patch stops on the assets, then on Podfile.lock after you pass
--allow-asset-diffs. Check out the Podfile.lock the release was built with,
or release again.
A patch for a release signed with your own key stops with exit code 64 if you don’t pass the keys (Shorebird 1.6.135 and newer). This happens in CI and locally. See Patch signing for the flags.
shorebird patch can’t find a release to patch
Section titled “shorebird patch can’t find a release to patch”A patch applies to one release, on one platform. shorebird patch stops when
there’s no finished release for it to apply to. Each message below is followed
by the command to run.
The release version doesn’t exist
shorebird patch stops with exit code 70 when no release matches
--release-version, or the version it read from the build. Check the version
for a typo, and with flavors, pass the same --flavor you released with: each
flavor has its own app ID. If that version was never released, release it, or
patch a version that was.
No release on this platform
Either the app has no release on this platform yet, or the patch is looking in
the wrong app. With flavors, each flavor has its own app ID in shorebird.yaml,
and a patch without --flavor uses the default app_id. Pass the same
--flavor you released with. If the app really has no release, create one with
shorebird release and publish that build to the store.
The release version exists, but not on this platform
The version was released on another platform only, for example Android. Run
shorebird release for this platform with the same version to add it to the
release, and publish that build.
The release didn’t finish
A shorebird release run for this version stopped before it finished, so the
release has no build to patch. Run shorebird release again for the same
version and publish the build from that run, or release a new version. Don’t
publish a build from the run that stopped: patches won’t install on it (see
Patches can’t install because the app isn’t the build Shorebird released).
If you deleted the release or the app, see If you deleted an app or release by mistake.
Patching an obfuscated iOS release built with older Flutter
Section titled “Patching an obfuscated iOS release built with older Flutter”shorebird patch ios stops with exit code 69 and an error like this:
An iOS patch is linked against its release, so it has to reuse the release’s
obfuscated names, and Flutter older than 3.41.2 can’t do that. A patch is always
built with its release’s Flutter version, so this release can’t be patched.
Create a new release with --obfuscate on Flutter 3.41.2 or newer, publish it
to the App Store, and patch that release. The Flutter version the current
Shorebird ships by default works too, so you can leave out --flutter-version.
The same applies to shorebird patch ios-framework. On other platforms, these
releases can still be patched, but each patch is obfuscated independently and
can be larger; see
Patch download size is unexpectedly large.
shorebird release says the release already exists
Section titled “shorebird release says the release already exists”shorebird release stops with exit code 70 and:
That version is already released on this platform, and a version can be released
only once per platform. Increase the build number (or the version) in
pubspec.yaml, or pass --build-number, and run shorebird release again. See
Release versions.
If you meant to ship a change to that release, run shorebird patch instead.
Aborting due to validation errors
Section titled “Aborting due to validation errors”Before building, shorebird release and shorebird patch check your project.
When a check finds an error, they print it and stop with
Aborting due to validation errors. Run shorebird doctor in your project to
see every check and its result. When some issues can be fixed for you, the
output ends with:
Run shorebird doctor --fix to apply those fixes, then commit the changed
files. The errors are:
android/app/src/main/AndroidManifest.xml is missing the INTERNET permission.Patches can’t download without it.--fixadds it....removes the INTERNET permission with tools:node="remove", but Shorebird needs it to download patches.Remove that<uses-permission>entry from the manifest.--fixdoesn’t change it....Release.entitlements is missing the Outgoing Connections (com.apple.security.network.client) entitlement., or theAllow Unsigned Executable Memoryentitlement. A macOS app needs both to download and run patches.--fixadds them.
shorebird doctor also prints these warnings, which don’t stop a release or a
patch:
pubspec.lock is not tracked in source control.Commit your lock files, so a patch builds with the same dependency versions as its release.- Xcode project
overrides FLUTTER_ build setting(s)warning. libapp.so.sym or libapp.so.dbg not presentwarning on Android, whichshorebird doctorreports as a legacykeepDebugSymbolsline.A new version of shorebird is available! Run `shorebird upgrade` to upgrade.
Some project problems stop a command with their own message instead:
-
A missing
shorebird.yaml:Run the command from your app’s root directory, or run
shorebird initif the app isn’t set up yet. -
shorebird.yamlnot listed as an asset:Add it under
assetsin thefluttersection ofpubspec.yaml, or runshorebird doctor --fix, which adds it. -
The iOS project has no Xcode scheme for flavor "staging". Add the scheme, or pass a flavor that has one. See the flavors guide. -
The project has flavors ..., but no --flavor argument was provided.is a warning: the command goes on with the defaultapp_id. Pass--flavorto release or patch a flavor.
Shorebird fails to install
Section titled “Shorebird fails to install”This can happen on Windows due to Windows’ limit of 260 characters for a path
(MAX_PATH). The same limit can also stop a build.
Shorebird 1.6.133 and older clone Flutter without long path support, so the clone can fail. Upgrade Shorebird, or run:
You may need to run this as an administrator, and you will need to restart your terminal after running this command. Shorebird 1.6.134 and newer enable long paths in their own Flutter clone and don’t need this.
Flutter 3.47.9 and newer (the default in Shorebird 1.6.135 and newer) stop with an error when a path in your build exceeds the limit:
Move your project to a shorter path (for example C:\src\my_app), or
enable long paths in Windows.
Can’t run your app in VS Code
Section titled “Can’t run your app in VS Code”If you see error output like the following when using the Run or Debug button in VS Code:
VS Code is probably using Shorebird’s version of Flutter instead of the Flutter
on your path. Shorebird builds resolve your project’s packages with Shorebird’s
Flutter, which records that Flutter in .dart_tool/package_config.json. The
Dart-Code extension older than v3.140 prefers that file over your PATH, so it
switches to Shorebird’s Flutter after a Shorebird build.
To fix it, do one of these:
-
Update the Dart extension in VS Code to v3.140 or newer, which prefers the Flutter on your
PATH. -
Run
flutter pub getwith your own Flutter after a Shorebird build. This rewritespackage_config.jsonto point at your Flutter. -
Explicitly provide VS Code with the path to your Flutter installation. In your
settings.jsonfile, add the line:Where “/path/to/flutter” is the path to your Flutter installation. You can get this by running
which flutterin your terminal (orwhere.exe flutteron Windows) and removing the/bin/flutterfrom the end of that path.
Shorebird 1.6.135 and older ran flutter pub get with the Flutter on your
PATH after every build to keep VS Code on your Flutter. That step could also
make Xcode’s Product > Archive fail after shorebird release. Shorebird 1.6.136
and newer no longer run it, so upgrade if you see that.
Could not find an option named “dart define”
Section titled “Could not find an option named “dart define””In PowerShell, Shorebird 1.6.131 and older drop the -- separator (see
this StackOverflow answer), so the
flutter build arguments after it fail with Could not find an option named.
Run shorebird upgrade, or quote the separator:
--dart-define and --dart-define-from-file don’t need the separator.
Xcode project overrides FLUTTER_ build setting(s) warning
Section titled “Xcode project overrides FLUTTER_ build setting(s) warning”shorebird doctor and shorebird init, and shorebird release and
shorebird patch for iOS, print this warning when your Xcode project hard-codes
a Flutter build setting:
Flutter sets FLUTTER_* build settings itself, in
ios/Flutter/Generated.xcconfig. A value hard-coded in the Xcode project takes
priority over that file. For example, a FLUTTER_ROOT that points at your own
Flutter install can make Xcode build part of your app with a different Flutter
than Shorebird’s, which can cause build failures. When the two installs are on
different Dart versions, the Xcode archive can fail with:
That message means a Dart tool read a file compiled by a different Dart version.
A hard-coded FLUTTER_ROOT is one cause. Another, which happens without this
warning, is a build phase that runs a globally activated Dart package, such as
flutterfire_cli uploading Crashlytics symbols: the package was compiled by the
Dart that activated it, and the build runs it with another. The lines after the
error then name the package, for example:
To fix the warning, remove each setting it names:
- Open
ios/Runner.xcworkspacein Xcode. - Select the Runner project, then the Build Settings tab.
- Search for
FLUTTER_. - Select each setting the warning lists and press Delete. Check every target and build configuration.
If the warning named FLUTTER_ROOT, removing it also fixes the kernel binary
error. If the error appears without the warning, as with a globally activated
package, release at the Flutter version you already use (Shorebird 1.6.123 or
newer): --flutter-version=fvm if you manage Flutter with
fvm, or --flutter-version=system for the flutter on your
PATH. Shorebird still builds with its own Flutter, but at that version, so
both use the same Dart. See
Match the Flutter version you already use.
FLUTTER_TARGET is allowed and never triggers the warning, since projects
commonly set it to a flavor’s entry point, such as lib/main_dev.dart.
For a Flutter module used with add-to-app, the check looks at
.ios/Runner.xcodeproj instead.
Your iOS build number is auto incrementing
Section titled “Your iOS build number is auto incrementing”Your iOS build number changes between shorebird release and the build that
reaches App Store Connect, so patches don’t install. A common cause is an
ExportOptions.plist that sets manageAppVersionAndBuildNumber to true, which
makes Xcode rewrite the build number on export. Shorebird needs you to control
your app’s version and build number, since a patch targets one release version.
When you pass that plist with --export-options-plist, shorebird release ios
and shorebird patch ios catch it before building and stop with:
To fix it, set manageAppVersionAndBuildNumber to false in your
ExportOptions.plist:
The CLI’s message also suggests removing the key, but set it to false instead:
when the export uploads to App Store Connect, Xcode treats a missing
manageAppVersionAndBuildNumber as true.
iOS app extension versions don’t match the app
Section titled “iOS app extension versions don’t match the app”Shorebird 1.6.125 and newer print this warning from shorebird release ios when
an app extension, such as a notification service extension, has a different
version or build number from your app, which App Store Connect rejects
(ITMS-90473):
Shorebird builds with Xcode’s “Manage Version and Build Number” off, so Xcode doesn’t update extension versions for you. The warning lists each extension’s values next to the app’s.
The release that printed the warning is already created, and shorebird release
refuses the same version again. To fix it:
- Bump your app’s build number in
pubspec.yaml. - In Xcode, set each extension target’s
MARKETING_VERSIONandCURRENT_PROJECT_VERSIONbuild settings to the app’s new version and build number. - Run
shorebird release iosagain.
Update the extensions’ versions together with the app’s on every release.
Invalid Podfile file
Section titled “Invalid Podfile file”You might see this error message if the FLUTTER_ROOT definition in your
project’s ios/Flutter/Generated.xcconfig points to a Shorebird Flutter
installation. This can be fixed by running any of:
flutter clean, orflutter build iosin your project’s root directory, orflutter runin your project’s root directory and targeting an iOS simulator/device.
Unsupported class file major version 65
Section titled “Unsupported class file major version 65”The error Unsupported class file major version 65 (or 66—the number varies
sometimes) happens when gradle is being executed with an incompatible Java
version.
You can check the specific Gradle version that your app is using by running
shorebird doctor -v inside the project folder. This command will also print
the Java version that Shorebird is using.
Refer to the official Gradle documentation to check which Java version works with which Gradle release.
Shorebird looks for Java in this order, and uses the first one it finds:
- The
jdk-dirFlutter setting, if you’ve set one. - The JDK bundled with Android Studio.
- The
JAVA_HOMEenvironment variable. - The
javaon yourPATH.
shorebird doctor -v prints the Java path it picked. Because Android Studio’s
JDK comes before JAVA_HOME, setting JAVA_HOME has no effect on a machine
with Android Studio installed. To use a different JDK there, set jdk-dir:
shorebird flutter config passes its arguments to Shorebird’s copy of
flutter config. Flutter stores jdk-dir in your user settings, not in the
SDK, so it also changes the JDK used by any other Flutter install on your
account. To go back to automatic detection, run
shorebird flutter config --jdk-dir=.
- Android Studio comes with a bundled JDK which should be auto-detected by Shorebird and might be the easiest way of solving the issue.
- If in a GitHub Action, the setup-java action can help.
- Or install the required Java version for your project’s Gradle release and
point
jdk-dirat it, orJAVA_HOMEif Android Studio isn’t installed.
Android build fails with “lower than Flutter’s minimum supported version”
Section titled “Android build fails with “lower than Flutter’s minimum supported version””Starting with Flutter 3.47, Android builds fail if your project uses a Gradle, Android Gradle Plugin (AGP), or Kotlin version older than Flutter’s minimum:
| Dependency | Minimum version |
|---|---|
| Gradle | 8.14 |
| Android Gradle Plugin | 8.11.1 |
| Kotlin | 2.2.20 |
Earlier Flutter versions only printed a warning for these versions. Java 17 remains the minimum Java version, unchanged. The error names the dependency that is too old:
The error also includes a “Potential fix” line pointing at the file to change.
Gradle is set in android/gradle/wrapper/gradle-wrapper.properties. AGP and
Kotlin are set in the plugins block of android/settings.gradle (or
settings.gradle.kts). Projects created from older templates set them in the
top-level android/build.gradle instead.
If you need to ship before upgrading, you can skip the check temporarily by passing Flutter’s flag:
Pass the same flag to shorebird patch android. Treat this as a stopgap:
Flutter doesn’t support building with these older versions.
libapp.so.sym or libapp.so.dbg not present warning on Android
Section titled “libapp.so.sym or libapp.so.dbg not present warning on Android”Starting with Flutter 3.44, the Android Gradle Plugin strips libapp.so and
produces a libapp.so.sym file, which Google Play Console uses to symbolicate
Dart crashes. If you see this warning when building an Android release:
your android/app/build.gradle (or build.gradle.kts) most likely still
contains this line, which some projects added to keep libapp.so unchanged for
Shorebird:
On Flutter 3.44 and newer, remove it. The line stops the Android Gradle Plugin
from stripping libapp.so, so no libapp.so.sym is produced. Your build still
succeeds, but Play Console won’t be able to symbolicate Dart crashes.
shorebird doctor warns you if the line is present.
On Flutter versions older than 3.44, keep the line.
The advice above applies to Flutter apps. If you
add Flutter to an existing Android app,
keep the line in your host app’s app/build.gradle on every Flutter version.
Missing a provisioning profile or no signing team was found
Section titled “Missing a provisioning profile or no signing team was found”This issue is addressed in the releasing guide. Take a look at the iOS section for more information.
shorebird preview can’t install an iOS release
Section titled “shorebird preview can’t install an iOS release”If shorebird preview fails to install an iOS release with an error about the
provisioning profile, the release’s archive was signed with a profile the device
doesn’t accept. An App Store distribution profile never installs on a device,
and a development or ad hoc profile only installs on the devices it includes.
See iOS signing for how to sign a release
that you can both preview and upload to the App Store.
Message saying patch might run slowly
Section titled “Message saying patch might run slowly”If shorebird patch warned that it was only able to share part of your Dart
code with the released app, or refused to publish because the link percentage is
below the minimum threshold, see
Link percentage and slow patches.
Sending a patch-debug.zip to Shorebird
Section titled “Sending a patch-debug.zip to Shorebird”shorebird patch ios writes build/patch-debug.zip when it
links the patch
against its release. Send it with any report of a slow patch or a low
shared-code percentage.
When it is produced
Section titled “When it is produced”Every shorebird patch ios run writes one. Android patches do not use the
linker and do not produce one.
Shorebird names it in the patch summary only when the link percentage is below 90%:
Even if you did not see that line, the file is still there.
Where to find it
Section titled “Where to find it”build/patch-debug.zip, relative to your project root. Codemagic respects
$CM_EXPORT_DIR, so it also shows up in your build artifacts there. On other CI
providers, archive it before the runner is torn down.
What is inside
Section titled “What is inside”The compiled Dart snapshots from both sides of the link, plus the link metadata Shorebird uses to compute the shared-code percentage. That is enough to reproduce the link and identify which code was not shared, without access to your project.
How to send it
Section titled “How to send it”Send your app ID, the release version, and the file.
A GitHub issue is usually easiest, and a public upload is fine for most apps. For a private app, use Discord, contact@shorebird.dev, or your shared Slack channel if you are an enterprise customer.
Resolving persistent compile or build failures
Section titled “Resolving persistent compile or build failures”If you encounter persistent compilation issues or strange env errors that standard builds do not trigger, the local compilation state or tool caches might be corrupted. You can clear all cached build states and tools to start fresh:
- Verify environment health:
- Clean standard build directories:
- Clean the Shorebird tools cache:
- Re-run your release or patch command.
Sign-in and credential errors
Section titled “Sign-in and credential errors”shorebird signs in with the first credential it finds: an API key in
SHOREBIRD_TOKEN, then GitHub Actions OIDC, then your shorebird login. Run
shorebird auth status to see which one it’s using (Shorebird 1.6.130 and
newer). Find the message you see:
You must be logged in to run this command.No credential was found. On your machine, runshorebird login. In CI, setSHOREBIRD_TOKENto an API key (see CI setup) or, in GitHub Actions, set up OIDC sign-in.Your Shorebird login has expired.orThe Shorebird auth service rejected your stored credentials (...). Your storedshorebird logincan’t be refreshed. Runshorebird loginagain.Could not refresh your Shorebird credentials: Could not reach the Shorebird auth service.orCould not refresh your Shorebird credentials: The Shorebird auth service sent an unexpected answer.Your login is unchanged, but the CLI couldn’t get an answer fromauth.shorebird.devit could use, such as when a proxy answers instead. Check your network, then try again. Behind a proxy or firewall, see below.SHOREBIRD_TOKEN is not a Shorebird API key (API keys start with sb_api_).The variable holds something other than an API key, most often a token from the oldshorebird login:ci. Create an API key in the Shorebird Console and set it asSHOREBIRD_TOKEN.No Shorebird account found for these credentials.The credentials are valid, but no Shorebird account matches them. Create an account in the Shorebird Console, or use the account you have: runshorebird logoutandshorebird login, or setSHOREBIRD_TOKENto one of its API keys.
For errors from GitHub Actions OIDC sign-in, see When a sign-in is refused.
Shorebird commands fail with network/TLS connection errors behind a proxy
Section titled “Shorebird commands fail with network/TLS connection errors behind a proxy”If your development machine or CI/CD runner is situated behind a corporate proxy or firewall, Shorebird CLI commands may fail to connect to Shorebird servers, showing timeout or TLS handshake errors.
To resolve this:
-
Configure proxy environment variables: Ensure that standard CLI proxy environment variables are set up in your terminal session:
- macOS/Linux:
- Windows (PowerShell):
-
Allow Shorebird’s hosts: Ensure your company firewall allows outbound HTTPS traffic (on port
443) to every host in Hosts Shorebird uses. That page also covers Gradle’s separate proxy settings and how to download from an internal mirror instead.
Patch download size is unexpectedly large
Section titled “Patch download size is unexpectedly large”Shorebird patches are usually small (a few hundred KB) because they only download the binary diff (patch artifact) of your compiled Dart code compared to the release version. If a patch size is unexpectedly large (several MBs):
- Upgraded dependencies: Adding or upgrading large third-party packages in
your
pubspec.yamlcan significantly change your compilation graph, causing a cascading code change that results in a larger diff. - Code generators: Extensive updates to code generation tools (e.g.,
build_runner,freezed,json_serializable) may modify large amounts of boilerplate code across dozens of files, resulting in a larger binary diff. - Obfuscation: you don’t need to match the release’s obfuscation yourself.
shorebird patchobfuscates the patch automatically when the release was built with--obfuscate, so leave the flag off. In CI, always pass--release-version; see Common causes. Passing--obfuscatefor a release built without obfuscation fails with--obfuscate was passed, but release <version> was not built with obfuscation.A patch can’t change a release’s obfuscation mode; create a new release instead. On every platform but iOS, a release built with--obfuscateon Flutter older than 3.41.2 can’t share its obfuscated names with its patches, so those patches are obfuscated independently and can be larger. A new release on Flutter 3.41.2 or newer avoids this.