Skip to content

AnalysisOptionsMigration ignores include:, repeatedly rewriting analysis_options.yaml files that already inherit the exclusions #191056

Closed

Description

@spydon

Steps to reproduce

AnalysisOptionsMigration (added in #187940, shipped in 3.47.0) decides whether a project needs migrating by reading only the literal contents of that project's own analysis_options.yaml. It never resolves include:, so a project that already inherits the exclusions from a shared analysis options file gets rewritten anyway, on every command that calls ensureReadyForPlatformSpecificTooling (flutter pub get, flutter analyze, flutter run, flutter build).

From a stock flutter create repro:

  1. Move the analyzer config into repro/shared_options.yaml:
    include: package:flutter_lints/flutter.yaml
    
    analyzer:
      exclude:
        - build/**
        - android/**
        - ios/**
        - web/**
        - windows/**
        - macos/**
        - linux/**
  2. Reduce repro/analysis_options.yaml to include: shared_options.yaml
  3. Confirm the inherited exclusions really are in effect. dart analyze doesn't run the migration, so it sees the unmodified file:
    $ printf 'int probe() => "nope";\n' > android/probe.dart && dart analyze
    No issues found!
    
    $ printf 'int probe() => "nope";\n' > lib/probe.dart && dart analyze
      error - lib/probe.dart:1:16 - A value of type 'String' can't be returned ... - return_of_invalid_type
    android/ is excluded, lib/ is still analyzed. The shared config works.
  4. flutter analyze

Expected results

No migration. The project already excludes every directory in excludesToExclude.

Actual results

$ flutter analyze
Upgrading analysis_options.yaml to exclude build and platform directories.

The file is rewritten to re-add the seven exclusions locally, duplicating what the included file already provides. Reverting and re-running any Flutter command adds them straight back, so there's no way to keep the config centralized.

This hurts monorepos with a shared lints package. supabase/supabase-flutter publishes a supabase_lints package that all 20 workspace packages include; putting the exclusions there analyzes correctly, but flutter pub get still rewrites all 20 files, so a routine pub get leaves every contributor with a 20-file dirty working tree.

Suggested fix

analysis_options_migration.dart#L50-L65 inspects root['analyzer']['exclude'] directly after loadYamlNode. Resolving include: (relative paths and package: URIs) before computing needsMigration would make it a no-op whenever the effective options already carry the exclusions, whichever file in the chain declares them.

If full include resolution is too costly for a path that runs on every command, a narrower fix would be to skip the migration when the local file is only an include: directive, or to add an opt-out flag.

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.47.0, on macOS 26.6.1 25G76 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
[!] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS and macOS development.
    ! CocoaPods not installed.
[✓] Chrome - develop for the web
[✓] Connected device (2 available)
[✓] Network resources

Activity

  1. rawi-coding commented on Aug 13, 2026

    @rawi-coding

    We have the same problem when using Dart Workspaces. In a project structured like this, it makes no sense to add platform specific exclusions to all analysis_options.yaml. It would be nice if at least the include: was respected as asked above or make this optional or opt-out.

    - app
        - ios
        - android
        - ...
    - component 1
    - component 2
    - ...
    

    The exclusion is only needed in the app workspace.

  2. saurabh-mirajkar commented on Aug 13, 2026

    @saurabh-mirajkar
    Contributor

    @spydon Thanks for the detailed report. I was able to reproduce this on Flutter 3.47.0. Labeling this and passing it on to tool team for further investigation.

  3. added
    toolAffects the "flutter" command-line tool. See also t: labels.
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    team-toolOwned by Flutter Tool team
    and removed
    in triagePresently being triaged by the triage team
    on Aug 13, 2026
  4. added
    P1High-priority issues at the top of the work list
    triaged-toolTriaged by Flutter Tool team
    on Aug 13, 2026
  5. self-assigned this
    on Aug 13, 2026
  6. added a commit that references this issue on Aug 13, 2026
  7. added a commit that references this issue on Aug 14, 2026
    74f87bd
  8. added a commit that references this issue on Aug 16, 2026
  9. added a commit that references this issue on Aug 26, 2026
  10. github-actions commented on Aug 31, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  11. locked as resolved and limited conversation to collaborators on Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work listfound in release: 3.47Found to occur in 3.47has reproducible stepsThe issue has been confirmed reproducible and is ready to work onteam-toolOwned by Flutter Tool teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-toolTriaged by Flutter Tool team

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions