skip to content

A team centralizes dependency repositories with FAIL_ON_PROJECT_REPOS, but their convention plugin still needs a special repository for plugins. Where does that go, and why doesn't the strict mode affect it?

level: seniorimportance: should knowfreq 25%

answer

  1. pluginManagement = plugins; dependencyResolutionManagement = deps
  2. repositoriesMode is on dependencyResolutionManagement only
  3. plugins resolved earlier, separate channel
  4. both blocks in settings.gradle.kts
  5. strict mode ignores plugin repos

basics

~10 s

Plugin repositories go in pluginManagement { repositories {} } in settings.gradle.kts. dependencyResolutionManagement and its repositoriesMode only govern regular dependency repositories, so FAIL_ON_PROJECT_REPOS doesn't touch plugin resolution.

solid answer

~40 s

Gradle keeps **plugin** resolution and **dependency** resolution on separate channels, each with its own settings block. Plugins are resolved from `pluginManagement { repositories { } }`; regular project dependencies are resolved from `dependencyResolutionManagement { repositories { } }`. The `repositoriesMode` property — including `FAIL_ON_PROJECT_REPOS` — lives on `dependencyResolutionManagement` and only governs that channel. So a special plugin repository (e.g. the Gradle Plugin Portal or an internal plugin repo) belongs in `pluginManagement.repositories`, and the strict dependency mode never sees it. This separation is deliberate: plugins are needed during initialization/configuration to even build the project model, so they're resolved earlier and through a distinct mechanism than the libraries your code compiles against. Both blocks live in `settings.gradle.kts`, but they don't share enforcement.

code

kotlin · 13 lines
kotlin
// settings.gradle.kts
pluginManagement {
    repositories {
        gradlePluginPortal()
        maven { url = uri("https://repo.mycorp.com/plugins") }
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        mavenCentral()
    }
}

go deeper

for a junior

Know plugin repos and dependency repos are configured in different blocks.

for a middle

Name pluginManagement.repositories vs dependencyResolutionManagement.repositories and that the mode only affects the latter.

for a senior

Explain the lifecycle reason (plugins resolved at init) and the failure case of a plugin injecting dependency repos.

for a principal

Discuss governing both channels with separate policy and how convention plugins should contribute to the central list rather than inject repos.

## Two separate resolution channels Gradle resolves two distinct kinds of artifacts, and they have **independent** repository configuration: 1. **Plugins** — applied via the `plugins { }` DSL or convention plugins. Resolved from repositories declared in: ```kotlin // settings.gradle.kts pluginManagement { repositories { gradlePluginPortal() maven { url = uri("https://repo.mycorp.com/plugins") } } } ``` 2. **Regular dependencies** — the libraries your production/test code compiles and runs against. Resolved from: ```kotlin dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral() } } ``` ## Why the strict mode doesn't touch plugins `repositoriesMode` is a property **on the `dependencyResolutionManagement` block**. It governs whether projects may declare *dependency* repositories. `pluginManagement` has no such mode and is resolved through a different code path, earlier in the lifecycle. Plugins must be available during **initialization/configuration** so Gradle can build the project model at all — so they cannot wait on the dependency-resolution machinery and aren't subject to its enforcement. ## Practical consequence A team can run a fully locked-down `FAIL_ON_PROJECT_REPOS` for dependencies while still adding whatever plugin repositories they need in `pluginManagement` — no conflict. The two blocks coexist in the same `settings.gradle.kts`: ```kotlin pluginManagement { repositories { gradlePluginPortal(); mavenCentral() } } dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { mavenCentral(); google() } } ``` ## Common confusion - People expect FAIL_ON_PROJECT_REPOS to also forbid `pluginManagement` repos — it doesn't. - Convention/precompiled script plugins sometimes try to add **dependency** repositories programmatically; *those* are caught by FAIL_ON_PROJECT_REPOS and must instead contribute to the central dependency list (or the plugin must be refactored).

  • Why are plugins resolved through a separate mechanism than dependencies?
    Plugins are needed during initialization/configuration to build the project model itself, so they must be resolved earlier and independently of the dependency-resolution machinery that compiles your code.
  • What if a convention plugin tries to add a dependency repository programmatically under FAIL_ON_PROJECT_REPOS?
    That counts as a project-level dependency repository and will fail the build. The fix is to put that repository in the central dependencyResolutionManagement block instead.

saying these in an interview costs you the question

  • Saying FAIL_ON_PROJECT_REPOS also blocks pluginManagement repositories.
  • Putting plugin repositories inside dependencyResolutionManagement.
  • Assuming the two blocks share a repositoriesMode.

context