Skip to content

[Gradle] Run DependencyVersionChecker before accessing Android DSL extensions in FlutterPlugin.apply - #194918

Merged
auto-submit[bot] merged 5 commits into
flutter:masterfrom
reidbaker-agent:fix-agp-version-check-order
Oct 22, 2026
Merged

auto-submit[bot] merged 5 commits into
flutter:masterfrom
reidbaker-agent:fix-agp-version-check-order

Conversation

@reidbaker-agent

@reidbaker-agent reidbaker-agent commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

Part of #180137, #166550.

I broke the check in PR 7/11 (#193693) in the new DSL migration for users that were on AGP 8.11. This fixes the mistake and adds a test. This will likely need to be cherry picked.

Agent authored details

Related PR

  • Follow-up PR: #195006. Because #194918 is a cherry-pick candidate, it only replaces the OUT_OF_SUPPORT_RANGE_PROPERTY check in FlutterPlugin.apply with a typed catch (e: DependencyValidationException). Removing OUT_OF_SUPPORT_RANGE_PROPERTY itself—which touches 7 property setters, a task action, and 14 test assertions across DependencyVersionChecker.kt and DependencyVersionCheckerTest.kt—is split into #195006 so this cherry-pick stays minimal.

Background

When #193813 (ce6e766ad1c) raised the minimum supported AGP version in DependencyVersionChecker to 9.1.1 and bumped the compile-time agpVersion in packages/flutter_tools/gradle/build.gradle.kts from 8.11.1 to 9.1.1, the Kotlin compiler began emitting AGP 9 binary method signatures for calls against ApplicationExtension (such as ApplicationExtension.getDefaultConfig()Lcom/android/build/api/dsl/ApplicationDefaultConfig;, whereas in AGP 8.x CommonExtension.getDefaultConfig() returned DefaultConfig without a covariant bridge on ApplicationExtension).

Because FlutterPlugin.apply invoked addFlutterTasks(project) (which calls configureAbis -> configureAbiWithoutSplits -> extension.defaultConfig.ndk and DslVersionCodes.from(appExtension) introduced in #193693 / #192488) before running DependencyVersionChecker.checkDependencyVersions(project), building an AGP 8.x project crashed during addFlutterTasks with:

java.lang.NoSuchMethodError: 'com.android.build.api.dsl.ApplicationDefaultConfig com.android.build.api.dsl.ApplicationExtension.getDefaultConfig()'

before reaching DependencyVersionChecker.checkDependencyVersions(project), preventing the user from seeing the actionable minimum AGP version error message and upgrade guidance.

Changes

  1. FlutterPlugin.kt:
    • Moves FlutterPluginUtils.detectApplyingKotlinGradlePlugin(project) and the shouldSkipDependencyChecks / DependencyVersionChecker.checkDependencyVersions(project) block to the beginning of FlutterPlugin.apply(project) (immediately after this.project = project), before addFlutterTasks(project) and all ApplicationExtension / Android DSL accesses.
    • Replaces the OUT_OF_SUPPORT_RANGE_PROPERTY extra-property check in FlutterPlugin.apply with a typed catch (e: DependencyValidationException) that rethrows DependencyValidationException directly and logs any other Exception, removing the comment that described OUT_OF_SUPPORT_RANGE_PROPERTY.
  2. FlutterPluginTest.kt:
    • Adds FlutterPlugin apply checks dependency versions before configuring project, verifying via verifyOrder that FlutterPluginUtils.detectApplyingKotlinGradlePlugin(project) and DependencyVersionChecker.checkDependencyVersions(project) run before task registration, AndroidComponentsExtension callbacks (finalizeDsl, onVariants), and ApplicationExtension DSL configuration (defaultConfig, buildTypes).
    • Adds FlutterPlugin apply rethrows DependencyValidationException and logs other exceptions, verifying both exception branches without relying on the extra property, and stubs supported Gradle and AGP versions in setupTestProjectEnvironment / setupMockComponentsExtension.
  3. packages/flutter_tools/gradle/AGENTS.md:
    • Updates the Matrix Verification bullet on line 40 to reference the supported AGP and Gradle versions defined in DependencyVersionChecker.kt.

Verification

  • Unit test negative/positive verification:
    • Moving DependencyVersionChecker after addFlutterTasks or moving detectApplyingKotlinGradlePlugin after DependencyVersionChecker fails FlutterPlugin apply checks dependency versions before configuring project.
    • Reverting the typed catch (e: DependencyValidationException) to the property check fails FlutterPlugin apply rethrows DependencyValidationException and logs other exceptions.
    • ./gradlew test with the fix applied: all tests pass.
  • End-to-end reproduction with AGP 8.11.1 and Gradle 9.3.1:
    • Before fix: failed at FlutterPlugin.configureAbiWithoutSplits with java.lang.NoSuchMethodError: 'com.android.build.api.dsl.ApplicationDefaultConfig com.android.build.api.dsl.ApplicationExtension.getDefaultConfig()'.
    • After fix: fails cleanly with Error: Your project's Android Gradle Plugin version (Android Gradle Plugin version 8.11.1) is lower than Flutter's minimum supported version of Android Gradle Plugin version 9.1.1. Please upgrade your Android Gradle Plugin version.
  • Formatting:
    • ktlint 1.5.0 with --editorconfig=dev/bots/test/analyze-test-input/.editorconfig --baseline=dev/bots/test/analyze-test-input/ktlint-baseline.xml passed with zero findings.

Pre-launch Checklist

…in FlutterPlugin.apply

After PR flutter#193813 bumped the compile-time AGP version in packages/flutter_tools/gradle/build.gradle.kts to 9.1.1, bytecode generated for FlutterPlugin.configureAbiWithoutSplits invokes ApplicationExtension.getDefaultConfig() with its AGP 9 return type signature. Because FlutterPlugin.apply invoked addFlutterTasks before DependencyVersionChecker.checkDependencyVersions, projects on AGP 8.x crashed with NoSuchMethodError before reaching the dependency version check.

Move the DependencyVersionChecker block before addFlutterTasks and update the supported AGP matrix rule in packages/flutter_tools/gradle/AGENTS.md.
@github-actions github-actions Bot added platform-android Android applications specifically tool Affects the "flutter" command-line tool. See also t: labels. labels Oct 21, 2026
@reidbaker-agent
reidbaker-agent marked this pull request as ready for review October 21, 2026 04:15
@reidbaker-agent
reidbaker-agent requested a review from a team as a code owner October 21, 2026 04:15
@reidbaker-agent
reidbaker-agent requested review from reidbaker and removed request for a team October 21, 2026 04:15
@reidbaker reidbaker added the CICD Run CI/CD label Oct 21, 2026
@reidbaker
reidbaker requested review from jesswrd and removed request for reidbaker October 21, 2026 04:15

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request moves the dependency version checking logic in FlutterPlugin to run earlier in the plugin application process, ensuring that unsupported AGP versions fail with a diagnostic error before accessing Android DSL extensions. It also updates the documentation in AGENTS.md and adds a corresponding unit test. The review feedback suggests simplifying the Gradle property lookups for usesUnsupportedDependencyVersions and skipDependencyChecks to avoid potential ClassCastException and improve code readability.

Comment on lines +146 to +148
if (!project.hasProperty("usesUnsupportedDependencyVersions") ||
!(project.properties["usesUnsupportedDependencyVersions"] as Boolean)
) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using as Boolean on a Gradle property lookup is unsafe because properties passed via the command line or gradle.properties are often parsed as String (e.g., "true"), which will cause a ClassCastException at runtime.

We can safely parse the property to a boolean using toString().toBoolean() and simplify the logic.

Suggested change
if (!project.hasProperty("usesUnsupportedDependencyVersions") ||
!(project.properties["usesUnsupportedDependencyVersions"] as Boolean)
) {
val usesUnsupported =
project.properties["usesUnsupportedDependencyVersions"]?.toString()?.toBoolean() == true
if (!usesUnsupported) {
References
  1. Suggest simplification and refactoring to enhance readability and maintainability, and optimize for readability. (link)

Comment on lines +137 to +141
val shouldSkipDependencyChecks: Boolean =
project.hasProperty("skipDependencyChecks") &&
(
project.properties["skipDependencyChecks"].toString().toBoolean()
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This property lookup can be simplified and made more idiomatic by using safe navigation and avoiding the explicit hasProperty check. This also reduces nesting and improves readability.

Suggested change
val shouldSkipDependencyChecks: Boolean =
project.hasProperty("skipDependencyChecks") &&
(
project.properties["skipDependencyChecks"].toString().toBoolean()
)
val shouldSkipDependencyChecks =
project.properties["skipDependencyChecks"]?.toString()?.toBoolean() == true
References
  1. Suggest simplification and refactoring to enhance readability and maintainability, and optimize for readability. (link)

every { mockComponentsExtension.pluginVersion } returns unsupportedAgpVersion
val extensionContainer = project.extensions
every { extensionContainer.getByType(ApplicationExtension::class.java) } throws
AssertionError("ApplicationExtension was accessed before DependencyVersionChecker rejected the AGP version")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a little too specific. I think we want to test hat DependencyVersionChecker runs before the code that relies on minimum version enforcement.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated in 85bd1984939: moved the DependencyVersionChecker.checkDependencyVersions(project) block to the start of FlutterPlugin.apply and replaced the test with FlutterPlugin apply checks dependency versions before configuring project, which uses verifyOrder to verify that DependencyVersionChecker.checkDependencyVersions(project) runs before task registration, AndroidComponentsExtension callbacks (finalizeDsl, onVariants), and ApplicationExtension DSL configuration (defaultConfig, buildTypes).

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 21, 2026
@reidbaker reidbaker added the CICD Run CI/CD label Oct 21, 2026
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 21, 2026
@reidbaker reidbaker added the CICD Run CI/CD label Oct 21, 2026
reidbaker
reidbaker previously approved these changes Oct 21, 2026
@reidbaker
reidbaker requested a review from gmackall October 21, 2026 16:07
gmackall
gmackall previously approved these changes Oct 21, 2026
@reidbaker-agent
reidbaker-agent dismissed stale reviews from gmackall and reidbaker via 0b5a8bf October 21, 2026 21:55
@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Oct 21, 2026
@reidbaker reidbaker added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 21, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 21, 2026
@auto-submit

auto-submit Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

auto label is removed for flutter/flutter/194918, Failed to enqueue flutter/flutter/194918 with HTTP 400: Something went wrong while executing your query on 2026-10-21T23:30:55Z. Please include B662:FEB8C:1DBFC2:5FDF54:6AD94B2F when reporting this issue..

@reidbaker reidbaker added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 22, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Oct 22, 2026
Merged via the queue into flutter:master with commit 0285737 Oct 22, 2026
36 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 22, 2026
@reidbaker reidbaker added the cp: beta cherry pick this pull request to beta release candidate branch label Oct 22, 2026
terence-truong pushed a commit to terence-truong/flutter that referenced this pull request Oct 22, 2026
…cyVersionChecker (flutter#195006)

Follow-up to flutter#194918; split out so that PR stays small for
cherry-picking.
Removes the `usesUnsupportedDependencyVersions`
(`OUT_OF_SUPPORT_RANGE_PROPERTY`) Gradle extra property from
`DependencyVersionChecker`, as `FlutterPlugin.apply` catches
`DependencyValidationException` directly and nothing else reads the
property.

Best the agent and my investigation work can find is that this was carry
over from when this code was in a build.gradle.kts file and we didnt
catch exceptions. I was found during manual review of flutter#194918

Part of flutter#166550.

<details><summary>Agent authored details</summary>

### Review Link (Part B diff only)

While [flutter#194918](flutter#194918) is open,
view only this PR's changes at:

https://github.com/flutter/flutter/pull/195006/files/5b5910facc17cd3d9ac87a594c187c6167f9ccc9..76d2f56c3e00ae37e016892bf7dcbe1c7fc8f675

### Background

`DependencyVersionChecker` set
`project.extra[OUT_OF_SUPPORT_RANGE_PROPERTY] = true`
(`"usesUnsupportedDependencyVersions"`) before throwing
`DependencyValidationException` and inside the `minSdkCheck` task
`doLast` action. That extra property originated when the dependency
version checker was applied as a standalone `.kts` script
(`dependency_version_checker.kts`) whose exception class could not be
referenced directly by `FlutterPlugin`. Because
`DependencyVersionChecker` and `DependencyValidationException` are
compiled in the same Kotlin module as `FlutterPlugin` and
[flutter#194918](flutter#194918) updated
`FlutterPlugin.apply` to catch `DependencyValidationException` directly,
the extra property has no remaining readers.

### Changes

1. **`DependencyVersionChecker.kt`**:
- Removes `OUT_OF_SUPPORT_RANGE_PROPERTY` and its 3-line comment
describing the Gradle extra property.
- Removes all 7 `project.extra.set(OUT_OF_SUPPORT_RANGE_PROPERTY, ...)`
calls (`checkDependencyVersions`, `configureMinSdkCheck`,
`checkGradleVersion`, `checkJavaVersion`, `checkAGPVersion` (x2), and
`checkKGPVersion`) and the `org.gradle.kotlin.dsl.extra` import.
- In `configureMinSdkCheck`, captures `rootDirPath`
(`project.rootDir.path`) and `minSdkVersion` outside `doLast` and passes
the task's `logger` to `checkMinSdkVersion(minSdkVersion, rootDirPath,
logger)` so the task action does not capture `Project`
(`packages/flutter_tools/gradle/AGENTS.md` §4).
- Updates the comment on `DependencyValidationException` to reference
`DependencyVersionChecker` instead of `the
dependency_version_checker.kts script`.
2. **`DependencyVersionCheckerTest.kt`**:
- Removes the `OUT_OF_SUPPORT_RANGE_PROPERTY`,
`ExtraPropertiesExtension`, and
`org.gradle.internal.extensions.core.extra` imports and mock setup,
keeping the `assertFailsWith<DependencyValidationException>` and logger
verification assertions in each test.
- Removed extra-property assertions (all redundant with
`assertFailsWith<DependencyValidationException>` or logger assertions
now that `OUT_OF_SUPPORT_RANGE_PROPERTY` is removed):
1. `Template versions are considered supported`: removed comment `//
Verify that the project was not marked as being out of support range.`
and `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, false)
}`.
2. `AGP version in error range results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
3. `AGP version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
4. `AGP version with unsupported major version results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
5. `AGP version above unsupported major version results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
6. `AGP version below unsupported major version is considered
supported`: removed `verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
7. `KGP version in error range results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
8. `KGP version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
9. `AGP 9 built-in Kotlin skips KGP min version enforcement by default`:
removed `verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
10. `Java version in error range results in error logs`: removed
`verify(exactly = 1) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
11. `Gradle version in error range results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
12. `Gradle version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
13. `min SDK version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
14. `min SDK version in error range results in
DependencyValidationException`: removed `verify(exactly = 1) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
15. `checkMinSdkVersion throws error when in error range for min SDK
version` and `checkMinSdkVersion logs warning when in warning range for
min SDK version`: removed unused `mockExtraPropertiesExtension` local
setup.
16.
`MockProjectFactory.createMockProjectWithSpecifiedDependencyVersions`:
removed `// Extra properties extension` comment and `mockProject.extra`
stubbing; stubbed `mockTask.logger` on the registered task mock.

</details>

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant in-code documentation (doc comments with
`///`).
- [x] If this PR introduces a new feature or capability, I created and
linked a website documentation issue or PR in [flutter/website] (or
verified none is needed).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/CONTRIBUTING.ai.md
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[flutter/website]: https://github.com/flutter/website
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
suryaKommana2662 pushed a commit to suryaKommana2662/flutter that referenced this pull request Oct 29, 2026
…tensions in FlutterPlugin.apply (flutter#194918)

## Description

Part of [flutter#180137](flutter#180137),
[flutter#166550](flutter#166550).

I broke the check in PR 7/11
([flutter#193693](flutter#193693)) in the new
DSL migration for users that were on AGP 8.11. This fixes the mistake
and adds a test. This will likely need to be cherry picked.

<details>
<summary>Agent authored details</summary>

### Related PR

- Follow-up PR:
[flutter#195006](flutter#195006). Because
`flutter#194918` is a cherry-pick candidate, it only replaces the
`OUT_OF_SUPPORT_RANGE_PROPERTY` check in `FlutterPlugin.apply` with a
typed `catch (e: DependencyValidationException)`. Removing
`OUT_OF_SUPPORT_RANGE_PROPERTY` itself—which touches 7 property setters,
a task action, and 14 test assertions across
`DependencyVersionChecker.kt` and `DependencyVersionCheckerTest.kt`—is
split into [flutter#195006](flutter#195006) so
this cherry-pick stays minimal.

### Background

When [flutter#193813](flutter#193813)
(`ce6e766ad1c`) raised the minimum supported AGP version in
`DependencyVersionChecker` to `9.1.1` and bumped the compile-time
`agpVersion` in `packages/flutter_tools/gradle/build.gradle.kts` from
`8.11.1` to `9.1.1`, the Kotlin compiler began emitting AGP 9 binary
method signatures for calls against `ApplicationExtension` (such as
`ApplicationExtension.getDefaultConfig()Lcom/android/build/api/dsl/ApplicationDefaultConfig;`,
whereas in AGP 8.x `CommonExtension.getDefaultConfig()` returned
`DefaultConfig` without a covariant bridge on `ApplicationExtension`).

Because `FlutterPlugin.apply` invoked `addFlutterTasks(project)` (which
calls `configureAbis` -> `configureAbiWithoutSplits` ->
`extension.defaultConfig.ndk` and `DslVersionCodes.from(appExtension)`
introduced in [flutter#193693](flutter#193693)
/ [flutter#192488](flutter#192488)) before
running `DependencyVersionChecker.checkDependencyVersions(project)`,
building an AGP 8.x project crashed during `addFlutterTasks` with:

```text
java.lang.NoSuchMethodError: 'com.android.build.api.dsl.ApplicationDefaultConfig com.android.build.api.dsl.ApplicationExtension.getDefaultConfig()'
```

before reaching
`DependencyVersionChecker.checkDependencyVersions(project)`, preventing
the user from seeing the actionable minimum AGP version error message
and upgrade guidance.

### Changes

1. **`FlutterPlugin.kt`**:
- Moves `FlutterPluginUtils.detectApplyingKotlinGradlePlugin(project)`
and the `shouldSkipDependencyChecks` /
`DependencyVersionChecker.checkDependencyVersions(project)` block to the
beginning of `FlutterPlugin.apply(project)` (immediately after
`this.project = project`), before `addFlutterTasks(project)` and all
`ApplicationExtension` / Android DSL accesses.
- Replaces the `OUT_OF_SUPPORT_RANGE_PROPERTY` extra-property check in
`FlutterPlugin.apply` with a typed `catch (e:
DependencyValidationException)` that rethrows
`DependencyValidationException` directly and logs any other `Exception`,
removing the comment that described `OUT_OF_SUPPORT_RANGE_PROPERTY`.
2. **`FlutterPluginTest.kt`**:
- Adds `FlutterPlugin apply checks dependency versions before
configuring project`, verifying via `verifyOrder` that
`FlutterPluginUtils.detectApplyingKotlinGradlePlugin(project)` and
`DependencyVersionChecker.checkDependencyVersions(project)` run before
task registration, `AndroidComponentsExtension` callbacks
(`finalizeDsl`, `onVariants`), and `ApplicationExtension` DSL
configuration (`defaultConfig`, `buildTypes`).
- Adds `FlutterPlugin apply rethrows DependencyValidationException and
logs other exceptions`, verifying both exception branches without
relying on the extra property, and stubs supported Gradle and AGP
versions in `setupTestProjectEnvironment` /
`setupMockComponentsExtension`.
3. **`packages/flutter_tools/gradle/AGENTS.md`**:
- Updates the `Matrix Verification` bullet on line 40 to reference the
supported AGP and Gradle versions defined in
`DependencyVersionChecker.kt`.

### Verification

- **Unit test negative/positive verification**:
- Moving `DependencyVersionChecker` after `addFlutterTasks` or moving
`detectApplyingKotlinGradlePlugin` after `DependencyVersionChecker`
fails `FlutterPlugin apply checks dependency versions before configuring
project`.
- Reverting the typed `catch (e: DependencyValidationException)` to the
property check fails `FlutterPlugin apply rethrows
DependencyValidationException and logs other exceptions`.
  - `./gradlew test` with the fix applied: all tests pass.
- **End-to-end reproduction with AGP 8.11.1 and Gradle 9.3.1**:
- Before fix: failed at `FlutterPlugin.configureAbiWithoutSplits` with
`java.lang.NoSuchMethodError:
'com.android.build.api.dsl.ApplicationDefaultConfig
com.android.build.api.dsl.ApplicationExtension.getDefaultConfig()'`.
- After fix: fails cleanly with `Error: Your project's Android Gradle
Plugin version (Android Gradle Plugin version 8.11.1) is lower than
Flutter's minimum supported version of Android Gradle Plugin version
9.1.1. Please upgrade your Android Gradle Plugin version.`
- **Formatting**:
- `ktlint 1.5.0` with
`--editorconfig=dev/bots/test/analyze-test-input/.editorconfig
--baseline=dev/bots/test/analyze-test-input/ktlint-baseline.xml` passed
with zero findings.

</details>

---

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant in-code documentation (doc comments with
`///`).
- [x] If this PR introduces a new feature or capability, I created and
linked a website documentation issue or PR in [flutter/website] (or
verified none is needed).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/CONTRIBUTING.ai.md
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[flutter/website]: https://github.com/flutter/website
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
suryaKommana2662 pushed a commit to suryaKommana2662/flutter that referenced this pull request Oct 29, 2026
…cyVersionChecker (flutter#195006)

Follow-up to flutter#194918; split out so that PR stays small for
cherry-picking.
Removes the `usesUnsupportedDependencyVersions`
(`OUT_OF_SUPPORT_RANGE_PROPERTY`) Gradle extra property from
`DependencyVersionChecker`, as `FlutterPlugin.apply` catches
`DependencyValidationException` directly and nothing else reads the
property.

Best the agent and my investigation work can find is that this was carry
over from when this code was in a build.gradle.kts file and we didnt
catch exceptions. I was found during manual review of flutter#194918

Part of flutter#166550.

<details><summary>Agent authored details</summary>

### Review Link (Part B diff only)

While [flutter#194918](flutter#194918) is open,
view only this PR's changes at:

https://github.com/flutter/flutter/pull/195006/files/5b5910facc17cd3d9ac87a594c187c6167f9ccc9..76d2f56c3e00ae37e016892bf7dcbe1c7fc8f675

### Background

`DependencyVersionChecker` set
`project.extra[OUT_OF_SUPPORT_RANGE_PROPERTY] = true`
(`"usesUnsupportedDependencyVersions"`) before throwing
`DependencyValidationException` and inside the `minSdkCheck` task
`doLast` action. That extra property originated when the dependency
version checker was applied as a standalone `.kts` script
(`dependency_version_checker.kts`) whose exception class could not be
referenced directly by `FlutterPlugin`. Because
`DependencyVersionChecker` and `DependencyValidationException` are
compiled in the same Kotlin module as `FlutterPlugin` and
[flutter#194918](flutter#194918) updated
`FlutterPlugin.apply` to catch `DependencyValidationException` directly,
the extra property has no remaining readers.

### Changes

1. **`DependencyVersionChecker.kt`**:
- Removes `OUT_OF_SUPPORT_RANGE_PROPERTY` and its 3-line comment
describing the Gradle extra property.
- Removes all 7 `project.extra.set(OUT_OF_SUPPORT_RANGE_PROPERTY, ...)`
calls (`checkDependencyVersions`, `configureMinSdkCheck`,
`checkGradleVersion`, `checkJavaVersion`, `checkAGPVersion` (x2), and
`checkKGPVersion`) and the `org.gradle.kotlin.dsl.extra` import.
- In `configureMinSdkCheck`, captures `rootDirPath`
(`project.rootDir.path`) and `minSdkVersion` outside `doLast` and passes
the task's `logger` to `checkMinSdkVersion(minSdkVersion, rootDirPath,
logger)` so the task action does not capture `Project`
(`packages/flutter_tools/gradle/AGENTS.md` §4).
- Updates the comment on `DependencyValidationException` to reference
`DependencyVersionChecker` instead of `the
dependency_version_checker.kts script`.
2. **`DependencyVersionCheckerTest.kt`**:
- Removes the `OUT_OF_SUPPORT_RANGE_PROPERTY`,
`ExtraPropertiesExtension`, and
`org.gradle.internal.extensions.core.extra` imports and mock setup,
keeping the `assertFailsWith<DependencyValidationException>` and logger
verification assertions in each test.
- Removed extra-property assertions (all redundant with
`assertFailsWith<DependencyValidationException>` or logger assertions
now that `OUT_OF_SUPPORT_RANGE_PROPERTY` is removed):
1. `Template versions are considered supported`: removed comment `//
Verify that the project was not marked as being out of support range.`
and `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, false)
}`.
2. `AGP version in error range results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
3. `AGP version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
4. `AGP version with unsupported major version results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
5. `AGP version above unsupported major version results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
6. `AGP version below unsupported major version is considered
supported`: removed `verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
7. `KGP version in error range results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
8. `KGP version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
9. `AGP 9 built-in Kotlin skips KGP min version enforcement by default`:
removed `verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
10. `Java version in error range results in error logs`: removed
`verify(exactly = 1) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
11. `Gradle version in error range results in
DependencyValidationException`: removed `verify {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
12. `Gradle version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
13. `min SDK version in warn range results in warning logs`: removed
`verify(exactly = 0) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
14. `min SDK version in error range results in
DependencyValidationException`: removed `verify(exactly = 1) {
mockExtraPropertiesExtension.set(OUT_OF_SUPPORT_RANGE_PROPERTY, true)
}`.
15. `checkMinSdkVersion throws error when in error range for min SDK
version` and `checkMinSdkVersion logs warning when in warning range for
min SDK version`: removed unused `mockExtraPropertiesExtension` local
setup.
16.
`MockProjectFactory.createMockProjectWithSpecifiedDependencyVersions`:
removed `// Extra properties extension` comment and `mockProject.extra`
stubbing; stubbed `mockTask.logger` on the registered task mock.

</details>

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant in-code documentation (doc comments with
`///`).
- [x] If this PR introduces a new feature or capability, I created and
linked a website documentation issue or PR in [flutter/website] (or
verified none is needed).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

If this change needs to override an active code freeze, provide a
comment explaining why. The code freeze workflow can be overridden by
code reviewers. See pinned issues for any active code freezes with
guidance.

**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/CONTRIBUTING.ai.md
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[flutter/website]: https://github.com/flutter/website
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD cp: beta cherry pick this pull request to beta release candidate branch platform-android Android applications specifically tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants