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>.
flutter-deep-link-handler-conflict¶
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.