Flutter lints are static rules that catch bugs and style issues before your app runs. This guide shows how to enable them, tune the rules, and enforce quality in CI for consistent, safer code.
Audience: IntermediateTested on: Flutter 3.x, Dart 3.x, macOS 14, Android 14 / iOS 17
Quick start: enable flutter_lints
Start with the official rule set. It strikes a good balance between safety and signal-to-noise.
# pubspec.yaml (excerpt)
dev_dependencies:
flutter_lints: ^<latest> # use the latest from pub.dev
# Create analysis_options.yaml at project root:
# analysis_options.yaml
include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- build/**
linter:
rules:
# add project-specific tweaks here
Run the analyzer:
dart analyze
# or
flutter analyze
Customize rules without causing churn
Start strict on correctness, lighter on style, then ratchet up. A common pattern:
# analysis_options.yaml (focused additions)
include: package:flutter_lints/flutter.yaml
linter:
rules:
always_declare_return_types: true
avoid_print: true
prefer_const_constructors: true
prefer_final_locals: true
unawaited_futures: true
analyzer:
language:
strict-casts: true
strict-inference: true
errors:
# escalate or downgrade severities (info | warning | error)
dead_code: error
unnecessary_cast: warning
Need an exception in code? Prefer targeted ignores:
// ignore: prefer_const_constructors
final w = Widget();
Linting for Flutter-specific patterns
- prefer_const_constructors: Build faster UIs by marking widgets constant.
- use_key_in_widget_constructors: Keep widget identity stable for diffing.
- avoid_redundant_argument_values: Let defaults speak; clearer APIs.
- unnecessary_await_in_return: Avoid extra microtasks in async code.
Organize options for mono-repos
Put a shared config in tool/analysis_options.yaml
and have packages include it:
# package A/B/C analysis_options.yaml
include: ../../tool/analysis_options.yaml
Wire lints into CI
Fail builds when new warnings appear. Example GitHub Actions step:
- name: Analyze
run: |
flutter pub get
dart analyze --fatal-infos --fatal-warnings
For incremental adoption, start with dart analyze
, then add --fatal-warnings
after the backlog is cleaned.
Security & pitfalls
- Too many global ignores: They hide real defects; prefer narrow
// ignore:
lines. - Over-styling: Style-only rules can drown signal; focus first on correctness and performance.
- Dead code drift: Keep
dead_code
as error to prevent unused branches accumulating.
FAQ
Q. flutter_lints vs. custom rules?
A. Start with flutter_lints for broad coverage; add a handful of custom rules that reflect your team’s priorities.
Q. Should warnings fail CI?
A. Yes—once the backlog is zero. Until then, gate only on errors to avoid blocking progress.
Q. How do I silence false positives?
A. Prefer targeted // ignore:
with a reason. If recurring, adjust the single rule in analysis_options.yaml
.
Conclusion
Enable flutter_lints
, add a few high-value rules, and enforce them in CI. Tune slowly to keep signal high. The result is a codebase that’s consistent, reviewable, and safer to change.
https://pub.dev/packages/flutter_lints
https://dart.dev/tools/linter-rules
https://docs.flutter.dev/development/tools/analysis
https://github.com/dart-lang/linter
Updated: 2025-10-09
Comment