When `update()` is called while another update (typically the automatic updater thread) is already running, the Rust updater previously bailed with `UpdateError::UpdateAlreadyInProgress`, which surfaced in Dart as `UpdateException: Update already in progress (unknown)`. This is the single highest-volume `UpdateException` in customer telemetry, yet the underlying situation is benign — the in-flight update continues on its own, the caller simply did not start a new one. Add a new `UpdateStatus::UpdateInProgress` variant and matching C status code `SHOREBIRD_UPDATE_IN_PROGRESS = 4`. `updater::update()` catches the `UpdateAlreadyInProgress` error from the lock helper and maps it to `Ok(UpdateStatus::UpdateInProgress)`. The Dart wrapper treats the new status as a successful return alongside `SHOREBIRD_UPDATE_INSTALLED`, so `update()` no longer throws for this case. Update the existing `usage_during_hung_update` c_api test to assert the new contract, and add a Dart test covering the in-progress return path. Version skew: new Dart on an old engine still sees the legacy `SHOREBIRD_UPDATE_ERROR` + "Update already in progress" message and will still throw. The fix lands once both sides ship. Partially addresses shorebirdtech/shorebird#3682 — does not resolve the broader asymmetry of `update()` semantics (it still does not wait for someone else's in-flight update to finish), which remains as v2 design work in shorebirdtech/shorebird#3684.
This Dart package communicates with the Shorebird Code Push Updater to:
- ✅ Get the currently installed patch version
- ✅ Check whether a new patch is available
- ✅ Download new patches
Demo
Explore this interactive demo to learn more
Getting Started
If your Flutter app does not already use Shorebird, follow our Getting Started Guide to add code push to your app.
Installation
flutter pub add shorebird_code_push
Usage
Shorebird automatically checks for and downloads updates in the background. Most apps do not need this package. This package is for apps that want additional control, such as displaying update status to the user or prompting before downloading.
Important: checkForUpdate() and update() make network calls that may
be slow. Avoid gating app startup on the result (e.g. awaiting in initState),
as the app may appear stuck on the splash screen. Use .then() instead.
import 'package:shorebird_code_push/shorebird_code_push.dart';
void main() => runApp(const MyApp());
// [Other code here]
class _MyHomePageState extends State<MyHomePage> {
final updater = ShorebirdUpdater();
Patch? _currentPatch;
bool _updateAvailable = false;
@override
void initState() {
super.initState();
// Read the current patch number (null if no patch is installed).
updater.readCurrentPatch().then((patch) {
setState(() => _currentPatch = patch);
});
// Check if an update is available to show in the UI.
updater.checkForUpdate().then((status) {
setState(() => _updateAvailable = status == UpdateStatus.outdated);
});
}
// [Other code here]
}
See the example for a complete working app.
Tracks
Shorebird supports publishing patches to different tracks, which can be used to target different segments of your user base. See the percentage based rollout guide for implementation details.
You must first publish a patch to a specific track (patches are published to the
stable track by default). To publish a patch to a different track, update your
patch command to use the --track argument:
shorebird patch android --track beta
(We're just using Android for this example. Tracks are supported on all platforms).
To check for updates on a given track, pass an UpdateTrack to
checkForUpdate (and update if you use it):
updater.checkForUpdate(track: UpdateTrack.beta);
You can also use custom track names. When creating a patch, specify a track name like this:
shorebird patch android --track my-custom-track
And:
updater.checkForUpdate(track: UpdateTrack('my-custom-track'));
Note: Updating to a specific track does not uninstall patches from other tracks. See #3484 for details.
Join us on Discord!
We have an active Discord server where you can ask questions and get help.
Contributing
See CONTRIBUTING.md.
