Flutter 3.47's Auto-Migration Silently Corrupts Analysis Configs
Any Flutter developer who runs `flutter pub get` on 3.47 risks having their `analysis_options.yaml` silently mutated. Teams using shared lint packages via `include:` will see duplicate exclusions injected on every command, and pure Dart web projects lose analyzer coverage of their `web/` source tree until they upgrade past the patched version.
Flutter 3.47 shipped an `AnalysisOptionsMigration` that runs during everyday commands like `flutter pub get` and `flutter analyze`. Its job is to add default platform-directory exclusions to `analysis_options.yaml`, but the initial implementation ignored the `include:` directive entirely, causing it to repeatedly append duplicate exclusions to monorepo configs that already inherited them from a shared package.
The second flaw was a hardcoded list of seven directories to exclude — `build/`, `android/`, `ios/`, `web/`, `windows/`, `macos/`, `linux/` — regardless of which platforms a project actually uses. For pure Dart web projects created with `dart create -t web`, this meant the genuine source directory `web/` was silently excluded from analysis.
Emergency patches landed within days. The fix now recursively resolves `include:` chains and canonical paths to avoid infinite loops, checks whether a package actually depends on Flutter before touching its config, and dynamically generates the exclusion list based on the platform directories that physically exist in the project.
A migration that mutates user source files should never run as a side effect of everyday commands; it belongs behind an explicit upgrade or doctor command.
The root cause is a review process that treated a destructive file mutation as a trivial template update, skipping the edge cases that `include:` and non-Flutter Dart projects represent.
Hardcoding platform knowledge into the tool rather than reading it from the project's actual filesystem state is a recurring source of Flutter tooling regressions.