Skip to content

Flutter

Flutter-specific checks: pubspec health, dependencies, assets, and ARB localization integrity.

34 checks.

flutter-analysis-diagnostics-suppressed

Severity: Medium

An excluded file is never analyzed and an ignored diagnostic is never reported, so flutter analyze and CI go green without having read that code. Bad casts, missing null checks and unhandled branches stay in it and surface only when it runs — in production for code that ships, and at the moment someone invokes it for code that does not.

How to fix: Remove analyzer: errors: <diagnostic>: ignore overrides for type-safety diagnostics. For analyzer: exclude:, open the hand-written files the evidence names and pick one remedy per glob. (1) Narrow the glob until it stops covering them — a codegen exclude usually wants the generated file-name suffix rather than the directory that holds it — which is the only remedy that puts those files back under a plain repo-root flutter analyze. (2) Keep the exclude and analyze that tree as its own step: it needs both an analysis_options.yaml of its own AND the path named in the command (dart analyze tools, in CI as well as locally). Both halves are required — a root run skips an excluded directory whether or not the nested options file is there.


flutter-cross-package-duplicate

Severity: Varies with what is found

Duplicate assets across packages inflate the final app bundle size unnecessarily.

How to fix: Create a shared assets package (e.g. packages/shared_assets/assets/) and move duplicates there, then reference it from each package's pubspec.yaml. This would save ~<totalWasted>.


Severity: High

Both handlers receive the same URL. The engine pushes the route it derives from the path while the plugin hands the URL to application code that pushes another one — so the app lands on the wrong screen, navigates twice, or drops the initial link on a cold start. Nothing fails mechanically, and a warm start behaves differently from a cold one, which is exactly why this reaches production and then resists reproduction.

How to fix: Pick one handler. To keep the plugin in charge, set FlutterDeepLinkingEnabled to false in the iOS Info.plist and add <meta-data android:name="flutter_deeplinking_enabled" android:value="false" /> to the Android activity. To use the engine's routing instead, drop the plugin and handle links through the router.


flutter-dependency-overrides

Severity: Medium

Dependency overrides mask version conflicts and can hide incompatibilities that surface only in production or when the overrides are removed.

How to fix: Resolve the underlying version conflicts so that dependency_overrides are no longer needed, or document why each override is required.


flutter-font-weight-undeclared

Severity: Medium

Flutter never infers weight or style from a font file's name. Without an explicit "weight:", the file collides with the family's default (400) face, and a TextStyle asking for that weight gets a synthesized fake bold from the default face instead of the real file — worse glyph metrics, while the intended file ships as dead weight in the bundle.

How to fix: Add the matching "weight:" (and "style:" for italics) to each non-default face in flutter.fonts, so Flutter selects the real file instead of synthesizing one.


flutter-git-dependency

Severity: Varies with what is found

git and external-path dependencies in production are non-reproducible and bypass pub.dev versioning. They can change underneath you and are a supply-chain risk.

How to fix: Publish the package to pub.dev and depend on a version, or pin the git dependency to an immutable ref (commit SHA).


flutter-heavy-dependency

Severity: Info

Heavy dependencies increase binary size, startup time, and may introduce complex native build requirements.

How to fix: Evaluate whether each heavy dependency is essential. Consider lighter alternatives or lazy-loading where possible.


flutter-heavy-svg

Severity: Medium

Complex SVG constructs (filters, masks, embedded images) are re-evaluated on every frame by flutter_svg, causing jank and increased GPU/CPU usage.

How to fix: Consider converting these SVGs to PNG or WebP for better rendering performance. If an SVG is used at multiple sizes, keeping it as vector may be preferable — in that case, try simplifying the heavy constructs.


flutter-icon-tree-shake-flag

Severity: Medium

Flutter subsets icon fonts at build time, keeping only the glyphs you actually reference (typically ~99% smaller). --no-tree-shake-icons turns that off and bundles the whole MaterialIcons/Cupertino font — the build stays green, the release just gets quietly bigger. The flag is usually a copy-paste workaround for IconTreeShakerException, which has a proper fix.

How to fix: Drop --no-tree-shake-icons and fix the underlying IconTreeShakerException: use const IconData with literal codepoints (no getter-backed / non-const IconData) so the tree-shaker can resolve the used icons.


flutter-impeller-disabled

Severity: Medium–Low

Falling back to Skia brings back lazy shader compilation, so the first run of an animation or a transition can stutter. With a tracked issue this is a deliberate, temporary trade — the risk is that it outlives the bug it was working around, since nothing fails once the flag is in place.

How to fix: Re-test with Impeller enabled once the linked issue is closed, and remove the flag.


flutter-incompatible-font-format

Severity: Medium

A .woff/.woff2 font is not rendered by Flutter — text silently falls back to a default font, so the intended typography never appears even though the build succeeds.

How to fix: Convert the font to .ttf or .otf and update the asset path in pubspec.yaml (Flutter does not support .woff/.woff2).


flutter-large-workspace

Severity: Low

Very large workspaces increase dependency resolution time, CI build duration, and make it harder to reason about package boundaries.

How to fix: Consider splitting the monorepo into smaller workspaces or using Melos/very_good_cli for better package management.


flutter-localization-duplicate-keys

Severity: Medium–Low

The file stays valid JSON, so no tool complains: gen_l10n generates from the surviving value and the earlier translation never ships. The usual cause is a merge that kept both sides, which means the two values are precisely the ones that differ — and the wrong one wins silently, in one locale, where only a speaker of that language will notice.

How to fix: Remove the losing occurrence of each duplicated key — keep the value the app should show, not the one that happens to be last. Add a lint step (or a pre-commit hook) that rejects duplicate keys, since JSON validation alone will never catch this.


flutter-localization-extra-keys

Severity: Low

Keys that exist only in non-template locales are dead translations that drift from the source of truth.

How to fix: Remove keys no longer in the template, or add them to the template if still needed.


flutter-localization-invalid-arb

Severity: High

An unparseable .arb file breaks gen-l10n / intl code generation for the whole build.

How to fix: Fix the JSON syntax (trailing commas, unescaped quotes) in the listed ARB files.


flutter-localization-invalid-metadata

Severity: Low

Malformed @-metadata (orphan @key or a non-object value) is ignored or rejected by gen-l10n and signals an editing mistake.

How to fix: Ensure every @key has a matching translation key and that its value is an object.


flutter-localization-missing-keys

Severity: Low

Keys present in the template locale are missing from other locales, so users there see the fallback language.

How to fix: Add the missing keys to each locale, or remove them from the template if unused.


flutter-localization-overview

Severity: Info

Understanding localization scope helps plan translation maintenance and detect unused strings.

How to fix: Review ARB files for unused keys and ensure all supported locales are complete.


flutter-localization-placeholder-metadata-drift

Severity: Low

Divergent @-metadata placeholder definitions across locales signal copy-paste drift and can confuse tooling.

How to fix: Keep @-metadata only in the template locale, or keep it identical across locales.


flutter-localization-placeholder-mismatch

Severity: Medium

A translation whose placeholder set differs from the template causes wrong substitutions or runtime format errors.

How to fix: Align each translation's placeholders ({name}, {count}) with the template message.


flutter-material-icons-missing-flag

Severity: Medium

Material icons need uses-material-design: true so Flutter bundles the MaterialIcons font. Without it the build still succeeds but the icons show as empty boxes at runtime — a quiet visual regression.

How to fix: Add uses-material-design: true under the flutter: section of the root pubspec.yaml.


flutter-missing-analysis-options

Severity: Medium

Without standard static-analysis rules, code style drifts and unsafe code goes unchecked, allowing avoidable bugs to reach production.

How to fix: Add an analysis_options.yaml (a single one at the repo/workspace root covers all nested packages) with include: package:flutter_lints/flutter.yaml.


flutter-missing-declared-asset-path

Severity: Medium

Declared but missing assets cause runtime errors or build failures. Flutter will fail to bundle assets it cannot locate, leading to broken images or crashes.

How to fix: Remove stale entries from flutter.assets in pubspec.yaml, or add the missing files to the expected paths.


flutter-missing-font-asset

Severity: Medium

Missing font files cause build failures or silent fallback to the default font, leading to inconsistent typography across the app.

How to fix: Add the missing font files to the declared paths, or remove stale font entries from pubspec.yaml.


flutter-non-recursive-asset-dir

Severity: Medium

Flutter includes only files directly inside a declared asset directory, not its subdirectories. Assets in an undeclared subdirectory are missing at runtime even though the build succeeds — a common "image works in debug but not release / not at all" trap.

How to fix: Add an explicit entry for each subdirectory in flutter.assets (e.g. - assets/img/sub/), since directory entries are not recursive.


flutter-plugin-permission-missing

Severity: Medium

A plugin that always needs an iOS purpose string (camera, microphone, location, bluetooth, biometrics, contacts, health, NFC, local network) crashes at runtime the moment its API is used without the string, and is a documented App Store rejection reason.

How to fix: Add the matching NS*UsageDescription key (e.g. NSCameraUsageDescription, NSLocationWhenInUseUsageDescription) to the app-target Info.plist with a clear justification — or remove the plugin if the feature is unused.


flutter-pubspec-overrides-shadowed

Severity: Medium

The team believes the pin in pubspec.yaml is applied, but pub resolves as though it were never written — no warning, no error, just a dependency graph that silently diverges from what was intended.

How to fix: Move the dependency_overrides from pubspec.yaml into pubspec_overrides.yaml (pub reads only the overrides file's dependency_overrides once it declares any), or delete pubspec_overrides.yaml's dependency_overrides section if it is unused.


flutter-pubspec-overview

Severity: Info

Understanding pubspec configuration helps identify bloat sources and dependency risks.

How to fix: Review dependency count and asset declarations for optimization opportunities.


flutter-secret-bundled-as-asset

Severity: Critical

A secret declared as a Flutter asset ships inside every install, not just the repository. Unlike a repo-only leak, extracting it needs no repository access at all — an APK/IPA is a zip, and unzipping it is enough.

How to fix: Rotate the credential first — "<path>" is already inside every copy of the app that has shipped, so deleting the file does not un-ship it. Then place the replacement by what it is, not by when it is injected. Public build configuration (an API base URL, a flavour flag, a public client id) belongs in --dart-define: the value is a compile-time constant, and wherever the app actually reads it, it ends up verbatim in the release binary — which is fine precisely because it is public. A credential cannot go there for the same reason, and injecting it from CI changes nothing — it compiles to the same bytes. Anything that must not reach users stays server-side: keep the privileged call behind a backend and have the app authenticate to obtain a short-lived, revocable, narrowly-scoped token instead.


flutter-split-debug-missing

Severity: Medium

Without --split-debug-info, debug symbols are included in the release binary, increasing size. Without --obfuscate, Dart code is not obfuscated, making reverse engineering easier.

How to fix: Add --split-debug-info=build/debug-info --obfuscate to flutter build commands for release builds.


flutter-uiscene-manifest-missing

Severity: High

Apple announced at WWDC25 that in the release following iOS 26, a UIKit app built with the latest SDK that has not adopted the UIScene life cycle will not launch. Flutter iOS hosts are UIKit apps, so the app builds, ships and passes review today — and then fails to start once Apple turns the warning into an assertion. Plugins that rely on scene callbacks (deep links, local_auth) also stop receiving them.

How to fix: On Flutter 3.41+ run flutter build ios to migrate eligible apps automatically. Otherwise add a UIApplicationSceneManifest entry to Info.plist with UISceneDelegateClassName = FlutterSceneDelegate, conform AppDelegate to FlutterImplicitEngineDelegate, and move GeneratedPluginRegistrant registration from didFinishLaunchingWithOptions into didInitializeImplicitFlutterEngine (requires Flutter 3.38+).


flutter-unused-asset

Severity: Medium

Unused assets are bundled uncompressed into the APK/IPA, directly increasing download size without providing any value to the user.

How to fix: For each asset, search for references with grep -r "<filename>" lib/ — if none, remove it from pubspec.yaml and delete the file.


flutter-vendored-packages

Severity: Medium

Vendored packages are local forks that miss upstream updates, security patches, and bug fixes. They also increase maintenance burden.

How to fix: For each vendored package, check if upstream has merged your changes. If so, switch back to the published version. If not, consider submitting a PR upstream.


flutter-weak-analysis-options

Severity: Low

Without standard static-analysis rules, code style drifts and unsafe code goes unchecked, allowing avoidable bugs to reach production.

How to fix: Extend the analysis_options.yaml with include: package:flutter_lints/flutter.yaml.