In this article

The Android flavor you intended to build is not proof of the flavor inside the artifact. Before uploading, compare the produced application ID, display name, configuration and backend mapping with an explicit release contract. This catches a successful build of the wrong app.

Flutter's Android flavors guide, checked October 8, 2026, explains product flavors and the --flavor build flag. This article focuses on verifying an existing setup rather than generating another flavor template.

Define the expected release before building#

For each environment, write down the expected package name, flavor, Dart entry point, backend environment, Firebase app mapping and signing configuration. Mark which values are public identifiers and which are secrets; never print the latter in CI.

For a hypothetical project:

text
Environment: production
Flavor: production
Entry point: lib/main_production.dart
Package: com.example.catalog
Backend: production service
Firebase mapping: production Android app

These illustrative names are not values to copy into your product. Use a distinct contract for staging. A familiar icon is a convenient signal, but it cannot prove that the embedded endpoints are correct.

Make the build selection explicit#

A project with a separate production entry point might use:

sh
flutter build appbundle --release \
  --flavor production \
  --target lib/main_production.dart

Use only names and files that exist in your repository. Preserve any required defines through the normal secure configuration path. A flavor flag and an entry-point flag serve different purposes; one does not automatically select every application-specific setting.

Record the source revision, lockfile and complete non-secret build arguments. If CI invokes a wrapper, inspect the arguments the wrapper actually passes.

Inspect the resulting application#

Open the artifact through Android Studio's supported analysis tools or your project's established bundle inspection process. Confirm the package identity and release variant, then compare the manifest and resources with the contract.

For backend mapping, add a safe test that distinguishes environments without exposing tokens. For example, an internal QA view can display a non-secret environment label; the verification should also confirm the request reached the intended test or production service through authorized logs.

Check Firebase mapping separately from the visual brand. Two environments can have identical names and icons while reporting analytics or crashes to different app records.

Resolve naming failures without widening the migration#

Flutter's current guide notes that Android Gradle Plugin 9 can reject flavor resValue() definitions when custom resource values are disabled. It demonstrates flavor-specific strings.xml resources for display names. See the display-name configuration.

Do not respond by replacing the entire Gradle configuration or enabling unrelated features. Determine whether the error is a resource-definition problem or a broader AGP compatibility issue.

Test the exact artifact and promote it#

Where your package identities allow it, install staging and production builds side by side on authorized QA devices. Verify that each reaches its intended environment and that deep links, notifications and crash reporting identify the correct app.

Retain the tested artifact's checksum and promote that artifact through your normal release process. Rebuilding after testing creates a new object that needs its own evidence, even when the version label is unchanged.

For reviewing a generated flavor patch, our AI code review guide helps separate plausible configuration from verified behavior. Stop an upload when the artifact identity does not match the contract; a green build is not sufficient.