skip to content

In Dart, when do you silence an analyzer finding with an ignore comment, ignore_for_file, analyzer errors: ignore, or analyzer exclude:?

level: middleimportance: should knowfreq 40%

answer

  1. narrowest scope that does the job
  2. one line, one file, one code, many files
  3. type=lint for generated files
  4. stale ignores get flagged too
  5. plugin codes carry a prefix

basics

~10 s

Use // ignore: for one line, // ignore_for_file: for one file (type=lint covers every lint), analyzer errors: <code>: ignore to drop one diagnostic package-wide, and analyzer exclude: to stop reporting whole files by glob.

solid answer

~40 s

Pick the narrowest scope. `// ignore: code` goes above the line or at its end and names one or more comma-separated codes, so a justified exception stays visible where it happens. `// ignore_for_file: code` covers the whole file wherever it sits; `// ignore_for_file: type=lint` silences every lint but not other diagnostics, which is why generators such as freezed write it into their output. `analyzer: errors: code: ignore` in `analysis_options.yaml` drops that diagnostic everywhere in the package. `analyzer: exclude:` takes globs and stops reporting anything for matching files. Since Dart 3.8 the `unnecessary_ignore` lint can flag an ignore for a diagnostic that is no longer produced, and `duplicate_ignore` flags one already covered. Diagnostics from an analyzer plugin are ignored as `plugin_name/code`, and `pubspec.yaml` accepts `# ignore:` comments since Dart 3.3.

code

dart · 7 lines
dart
// ignore_for_file: avoid_print

void main() {
  // ignore: unused_local_variable
  final debugOnly = DateTime.now();
  print('seeding local data');
}

go deeper

for a junior

Recall the syntax of // ignore: and // ignore_for_file:, and that a comma-separated list names several codes.

for a middle

Explain the four scopes, why generated files carry type=lint, and why exclude: hides real errors along with the noise.

for a senior

Show a policy: narrowest suppression, a reason beside each ignore, unnecessary_ignore on, and team-rejected rules disabled centrally.

for a principal

Frame suppressions as tracked debt, deciding when a rule with many ignores should be dropped from the shared set instead.

## Four scopes of suppression Every analyzer finding has a **code**: `unused_local_variable`, `dead_code`, `avoid_print`, `deprecated_member_use` and so on. Dart gives you four ways to stop a finding being reported, and they differ in **scope**: | Mechanism | Where it lives | Scope | |---|---|---| | `// ignore: code` | Dart source, above or at the end of a line | that one line | | `// ignore_for_file: code` | Dart source, anywhere in the file | the whole file | | `analyzer: errors: code: ignore` | `analysis_options.yaml` | every file in the package | | `analyzer: exclude: <glob>` | `analysis_options.yaml` | every diagnostic in matching files | The rule of thumb is to use the **narrowest** one that solves the problem, so the exception stays close to the code that needs it and does not hide unrelated findings. ## Line and file comments A line comment either sits on the line above the code or is appended to it: ```dart // ignore: deprecated_member_use final old = legacyApi(); int count = parse(raw); // ignore: unnecessary_cast ``` Both forms take a **comma-separated list** of codes. A file comment has the same syntax with `ignore_for_file`, and applies to the whole file regardless of where it appears, before or after the code in question. The special specifier **`type=lint`** matches every lint rule: ```dart // ignore_for_file: type=lint ``` It does not silence analyzer warnings or errors, only lints. This is the standard header for **generated code**. freezed's generated `.freezed.dart` files start with `// GENERATED CODE - DO NOT MODIFY BY HAND` followed by `// ignore_for_file: type=lint` and a list of specific warning codes, because your project's lint choices should not fire on code nobody edits by hand. ## Package-wide and file-wide switches - **`analyzer: errors: todo: ignore`** removes one code from every file. Use it when the team has decided a diagnostic is not wanted at all. For a lint rule, setting it to `false` under `linter: rules:` has the same practical effect and reads more clearly. - **`analyzer: exclude:`** takes globs relative to the options file, such as `build/**`, `lib/**.g.dart` or `test/_data/**`. It is the bluntest tool: real errors in those files disappear as well. Keep it for build output, vendored code and generated files you never want reported. ## Keeping ignores honest Suppressions rot. A comment that once hid a real finding keeps sitting there after a refactor removes the cause. Two diagnostics help: 1. **`unnecessary_ignore`** (a lint, since Dart 3.8) reports an ignore for a diagnostic that is not produced at that location or in that file. Turn it on to have stale ignores surface as findings. 2. **`duplicate_ignore`** reports a code named twice, for example in both an `ignore` and an `ignore_for_file` comment. Many teams also require a short reason next to each ignore in code review, so the exception documents itself. ## Special cases - **Analyzer plugins** (Dart 3.10+): prefix the code with the plugin name and a slash, as in `// ignore: some_plugin/some_code` or `// ignore_for_file: some_plugin/some_code`. - **`pubspec.yaml`**: since Dart 3.3 a `# ignore: code` comment above a line suppresses a non-error diagnostic there, for example `sort_pub_dependencies` when the `flutter` SDK dependency must stay first. - **`dart fix`** can remove many findings automatically; that tool belongs with the other `dart` commands, but it is often a better answer than an ignore. ## Choosing in practice - A single justified call to a deprecated API: a line `ignore`. - A test file that deliberately prints output: `ignore_for_file: avoid_print`. - A generated part that trips lints: rely on its `type=lint` header, or `exclude:` the glob. - A rule the team rejects: switch it off in `linter: rules:` rather than scattering ignores. - A folder of fixtures or sample data that is not meant to compile cleanly: `exclude:` it, since nothing in it is maintained as code. ## What reviewers look for A suppression is a small, local decision to accept a finding, and code review is where it gets checked. Reviewers typically ask: 1. **Is it precise?** Each comment should name only the codes that line or file really triggers; a long list copied from another file hides more than intended. 2. **Is the scope minimal?** A file-wide ignore to hide one line, or a package-wide `ignore`, is usually a sign the change should be narrower. 3. **Is there a reason?** A short note beside the comment, such as why a deprecated API is still needed, saves the next reader from reverse-engineering it. 4. **Will it expire?** Suppressions tied to a migration should be removed when the migration lands; `unnecessary_ignore` makes the leftovers visible.

  • Why does generated code usually carry ignore_for_file: type=lint rather than being excluded?
    The header travels with the file, so every consuming project gets the suppression without editing its own options. It also silences only lints: if a generator ever emits code with a real warning or error, you still see it, whereas an `exclude:` glob would hide that too.
  • How would you find ignore comments that no longer suppress anything?
    Enable the `unnecessary_ignore` lint, available since Dart 3.8. It reports an ignore naming a diagnostic that is not produced at that line or in that file, so stale suppressions show up in `dart analyze` output and can be deleted.

saying these in an interview costs you the question

  • Excludes whole folders from analysis to silence one noisy lint
  • Thinks ignore_for_file only applies to code below the comment
  • Believes type=lint also hides analyzer warnings and errors
  • Assumes stale ignore comments can never be detected
  • Scatters line ignores for a rule the team rejects instead of disabling it