Flitzdocs
Loader plugins

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 matchCheckedWhat you seeFix
The Flitz SDK. The host was built with, and the bundle published with, the same SDK tag.When a bundle loadsBundle invalid: Platform dill hash mismatchBuild 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 loadsBundle invalid: Bundle requires native packages not available in this hostAdd 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 loadsBuild error: Flitz loader plugin <version> needs a Flitz SDK at iteration <N> or newer…; on the device: Loader needs a newer SDKPin 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 loadsBundle 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 loadsBuild error: … is not a Flitz release SDK …; on the device: Loader build is broken, naming flitz_host.jsonPoint 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 with MissingPluginException. 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, and asFunction.
  • Does not work: NativeCallable (native-to-Dart callbacks) — constructing one throws This 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 configure picks 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:

  1. The pin decides the SDK for both sides. Build the host and publish with it.
  2. Use the loader-plugin version flitz plugins configure prints for the pin. After moving the pin, re-run it, update the plugin if the version changed, and rebuild the host.
  3. 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 version flitz plugins configure prints and rebuild the host.

On this page