Compatibility
What must match between a host and a bundle, when it is checked, and how to fix a mismatch.
A bundle runs only on a host that can provide everything it needs. The loader checks that before any of the bundle's code runs, and every failure names the side to fix under one of three titles:
- Bundle invalid — the bundle does not fit this host. Publish a matching bundle, or add what it needs to the host.
- Loader build is broken — the host build itself is wrong. Every bundle is refused until the host is rebuilt correctly.
- Loader needs a newer SDK — the host was built with a Flitz SDK older than its loader-plugin version supports. Rebuild the host with a newer SDK.
See How it works for the concept; this page covers the rules and their fixes.
What must match
| What must match | Checked | What you see | Fix |
|---|---|---|---|
| The Flitz SDK. The host was built with, and the bundle published with, the same SDK tag. | When a bundle loads | Bundle invalid: Platform dill hash mismatch | Build the host and publish bundles with the tag your project pins. After moving the pin, rebuild and reinstall the host. |
| Native packages. The host ships every package with native code that the bundle's app depends on. | When a bundle loads | Bundle invalid: Bundle requires native packages not available in this host | Add the missing packages to the host's pubspec.yaml, run flutter pub get, then rebuild and reinstall the host. |
| The loader-plugin version. The host's SDK is at or above the plugin version's minimum iteration. | When you build the host, and when a bundle loads | Build error: Flitz loader plugin <version> needs a Flitz SDK at iteration <N> or newer…; on the device: Loader needs a newer SDK | Pin a newer SDK with flitz sdk use, or use the plugin version flitz plugins configure prints for your pin. |
| The bundle format. The CLI that published the bundle and the loader plugin in the host read and write the same format. | When a bundle loads | Bundle invalid: Unsupported bundle version: <n> | Update whichever side is older: the CLI (re-run the install script, then flitz publish again), or the loader plugin (then rebuild the host). |
A Flitz host build. The host was built with the Flitz SDK's flutter. | When you build the host, and when a bundle loads | Build error: … is not a Flitz release SDK …; on the device: Loader build is broken, naming flitz_host.json | Point your toolchain at the pinned SDK (flitz sdk path prints it) and rebuild the host. |
Running a build from the panel goes through the same checks. The panel lists every build on a track, including ones this host cannot run, and those fail with the errors above.
The loader does not check which app a bundle came from: any bundle that passes these checks runs, whatever app it was built from. That is a fact about fit, not trust — only run bundles your own team publishes. Who may download a bundle is a separate, per-app setting: when an app's download access is Members only, its bundles download only into a host with sign-in, for a member of the app's organization. See Download access.
Native packages
Everything native lives in the host: the Flutter engine, the compiled Dart runtime, every plugin's platform code, and every native library. A bundle only uses them. So the host must ship every package with native code that the bundle's app depends on:
- What counts: a plugin with a native platform implementation, or a
package with a native build hook (
hook/build.dart), anywhere in the bundle app's dependency graph — direct or transitive, called or not. Dart-only packages and dev dependencies do not count. - How they match: by package name. The Flitz SDK records both lists when it builds the host and the bundle; you never maintain a list by hand.
- The simple rule: build the host and publish bundles from the same
pubspec.yaml. After adding a native package, rebuild and reinstall the host before you publish bundles that use it.
Only names are compared, not versions. Keep native plugin versions the same on both sides: a bundle on a newer version of a native plugin than the host was built with can fail at run time.
Plugin registration
The loader validates plugins up front; registering them on the bundle's engine is a separate step:
- Android: the bundle's engine registers your plugins automatically. Nothing to write.
- iOS: the loader calls your
registerPlugins(with:)override once per bundle engine. The override is required; without it the bundle has no plugins and method-channel calls fail withMissingPluginException. See the iOS quickstart.
Plugins that rely on FlutterPluginRegistrar.addApplicationDelegate(_:) may not
work inside bundles, because the bundle engine's registrar is invoked outside
the standard iOS app-delegate forwarding chain. We are working on a fix.
FFI
Bundles may call native code through dart:ffi, but only native code the host
already ships. FFI packages with a native build hook are native packages in the
sense above: the host must depend on them too, so their native libraries are
compiled into the host.
- Works:
Pointer,Struct,Union,Array,@Native,DynamicLibrary.open/.process/.executable,NativeFinalizer, allocators,lookupFunction, andasFunction. - Does not work:
NativeCallable(native-to-Dart callbacks) — constructing one throwsThis function should be handled on call site.Passing a struct or union by value as an argument, and returning a large struct by value, are not supported either; pass them by pointer. We are working on a fix.
A bundle cannot bring its own native code: the archive carries none, and the
loader never downloads or opens a library the bundle names. If an FFI package's
build hook produces native assets in a form the loader does not support, every
bundle fails with "Loader build is broken" naming NativeAssetsManifest.json;
update or replace that package and rebuild the host.
SDK and plugin versions
Two version numbers meet in the loader.
The Flitz SDK tag — <flutter-version>+flz.<N> — is what your host and your
bundles are built with. <N> is the Flitz iteration: it increases with every
Flitz release and is shared across Flutter versions. The host and every bundle
it runs must use the same tag.
The loader-plugin version follows its own semver. Each plugin version supports Flitz SDKs from a minimum iteration upward, on any Flutter version.
flitz plugins configurepicks the newest plugin version that supports the iteration of your pinned SDK — or of the latest SDK, when the project pins none — and prints it. When no published plugin version supports your SDK, it says so and suggests an SDK to pin.- The recommendation is exactly that: the CLI never reads your Gradle, Podfile, or SwiftPM files, so it reports what your project should use. Run it again after moving your SDK pin.
- The minimum is enforced twice. Building a host with an older SDK fails with
Flitz loader plugin <version> needs a Flitz SDK at iteration <N> or newer…, and a host that got past that refuses every bundle with "Loader needs a newer SDK".
flitz status checks your pin and whether a loader-plugin version supports it.
It does not read your host's build files: to confirm the host is built with the
pinned SDK, check that flutter --version — or flutter.sdk in
android/local.properties — points at the path flitz sdk path prints.
Keeping versions aligned
Three things move independently: the SDK pin, the loader-plugin version, and the CLI. Keep them in step:
- The pin decides the SDK for both sides. Build the host and publish with it.
- Use the loader-plugin version
flitz plugins configureprints for the pin. After moving the pin, re-run it, update the plugin if the version changed, and rebuild the host. - After updating the CLI, publish a bundle and open it on your host. If the
host refuses it with
Unsupported bundle version, update the loader plugin to the versionflitz plugins configureprints and rebuild the host.