skip to content

Plugin Version Resolution

Where a plugin's version comes from: declared inline, already resolved elsewhere in the build, or taken from a version catalog with alias(libs.plugins.x). Asked because the same plugin versioned twice in two subprojects is a common failure.

on this pageshow

questions

5

How do you declare a plugin and its version in the plugins {} block, and where does Gradle resolve that plugin from?

level: juniorimportance: must knowfreq 75%

answer

  1. id + version literal
  2. marker artifact lookup
  3. pluginManagement repositories
  4. Plugin Portal default
  5. core plugins take no version

basics

~10 s

Use id("com.example.foo") version "1.2.3" inside plugins {}. Gradle resolves the plugin from the Gradle Plugin Portal (or repositories declared in settings' pluginManagement) by looking up its marker artifact.

solid answer

~40 s

Inside the `plugins {}` block you write `id("com.example.foo") version "1.2.3"` (Kotlin DSL) or `id 'com.example.foo' version '1.2.3'` (Groovy). The `id` is the plugin's globally unique identifier; `version` pins which release to fetch. Gradle resolves it by requesting a *plugin marker artifact* (`com.example.foo:com.example.foo.gradle.plugin:1.2.3`) whose POM points at the real implementation jar. Resolution sources are configured in `settings.gradle(.kts)` under `pluginManagement { repositories { ... } }`, which defaults to the Gradle Plugin Portal plus `gradlePluginPortal()`. Core Gradle plugins like `java` or `application` are bundled with the distribution, so they take no version. For third-party plugins the version is mandatory unless it was already resolved elsewhere (e.g. the root project or a version catalog).

code

kotlin · 14 lines
kotlin
// build.gradle.kts
plugins {
    id("java")                                  // core, no version
    id("org.springframework.boot") version "3.3.0"  // third-party, version required
    kotlin("jvm") version "2.0.0"
}

// settings.gradle.kts
pluginManagement {
    repositories {
        gradlePluginPortal()
        mavenCentral()
    }
}

go deeper

for a junior

Know the id("x") version "y" syntax and that the Plugin Portal is the default source.

for a middle

Explain the marker-artifact lookup and that repositories come from settings' pluginManagement.

for a senior

Discuss core-vs-third-party versioning rules and why versions must be literals in the block.

for a principal

Frame centralizing plugin versions (pluginManagement/catalog) as a governance lever across many repos.

## What the version does The `plugins {}` block is the modern, declarative way to apply Gradle plugins. Each entry has an **id** (a reverse-DNS string like `org.springframework.boot`) and optionally a **version**. The version tells Gradle *which release* of the plugin to download and put on the build script classpath. ```kotlin plugins { id("org.springframework.boot") version "3.3.0" kotlin("jvm") version "2.0.0" // sugar for id("org.jetbrains.kotlin.jvm") } ``` ## Where Gradle resolves it from When you give an id + version, Gradle looks up a **plugin marker artifact**. For id `foo.bar` it requests `foo.bar:foo.bar.gradle.plugin:<version>`. That tiny artifact's POM declares a dependency on the actual implementation jar. This indirection lets the plugin author rename/relocate the implementation without changing the id you type. The **repositories** searched come from `settings.gradle.kts`: ```kotlin pluginManagement { repositories { gradlePluginPortal() // default mavenCentral() google() } } ``` If you declare no `pluginManagement.repositories`, Gradle defaults to the **Gradle Plugin Portal**. ## Core vs third-party - **Core plugins** (`java`, `java-library`, `application`, `jacoco`, ...) ship inside the Gradle distribution. You apply them with `id("java")` and **no version** — versioning them is an error. - **Community/third-party plugins** require a version (in the block, in the catalog, or already resolved by a parent — see follow-ups). ## Constraints of the plugins {} block The block is evaluated very early, before the rest of the script. Versions must be **literal strings** — you cannot compute them from variables or `project.property(...)` directly inside `plugins {}`. To keep versions out of build scripts, use `pluginManagement.plugins {}` in settings or a **version catalog** (`alias(libs.plugins.x)`).

  • What is a plugin marker artifact and why does it exist?
    A small published artifact `id:id.gradle.plugin:version` whose only job is to redirect to the real implementation jar via its POM dependencies. It decouples the stable plugin id from the implementation coordinates, so authors can relocate or rename the implementation without breaking consumers.
  • Can you use a variable for the version string inside plugins {}?
    No — the block is parsed specially and early, so versions must be literal strings (or come from a version catalog/pluginManagement). Computing them with a Groovy/Kotlin expression in the block is not allowed.

saying these in an interview costs you the question

  • Claiming every plugin needs a version (core plugins must NOT be versioned).
  • Saying plugins resolve from mavenCentral/jcenter by default — the default is the Gradle Plugin Portal.
  • Thinking the version string can be a build variable inside the plugins {} block.

context

open as a page

When can you apply a plugin in plugins {} without specifying a version, and how does Gradle know which version to use?

level: middleimportance: must knowfreq 65%

basics

~10 s

You omit the version when it's already resolved elsewhere: core Gradle plugins (bundled), plugins versioned in settings' pluginManagement.plugins {}, or a version brought in by a parent/root project. Gradle reuses that already-known version.

open as a page

How do you apply a plugin using a version catalog (libs.versions.toml) with alias(libs.plugins.x), and how is the version wired in?

level: middleimportance: must knowfreq 60%

basics

~10 s

Define the plugin under [plugins] in gradle/libs.versions.toml (id + version, version can reference [versions]). Then in plugins {} write alias(libs.plugins.x). Gradle generates the typesafe libs accessor and supplies the version from the catalog.

open as a page

A build fails with a plugin version conflict (the same plugin requested at two different versions). How do you diagnose and fix it?

level: seniorimportance: should knowfreq 40%

basics

~10 s

Find every place the plugin's version is declared (catalog, settings pluginManagement, root and module plugins blocks). Keep exactly one declaration as the source of truth, omit the version everywhere else, and re-run the build.

open as a page

In a large multi-module build, how would you structure plugin version resolution so versions are declared once and applied consistently across modules?

level: seniorimportance: should knowfreq 45%

basics

~20 s

Declare every plugin version once in gradle/libs.versions.toml under [plugins]. Resolve them at the root with alias(...) apply false (or use convention plugins), then apply by alias with no version in each module. This keeps versions DRY and conflict-free.

open as a page