skip to content

If you apply a plugin by id in build.gradle without a version, where does Gradle get the version from?

level: juniorimportance: should knowfreq 30%

answer

  1. Gradle never invents a version
  2. eachPlugin useVersion OR catalog alias
  3. else 'requested without a version' error
  4. gradle.properties not auto-wired
  5. central = clean scripts + no drift

basics

~10 s

From a central source: a useVersion call in settings.gradle's eachPlugin hook, a version catalog plugins alias, or because a parent/settings already pinned it. Without any of these, resolution fails.

solid answer

~40 s

A bare `id 'com.example.foo'` with no version means the version must come from elsewhere. The two main central sources are: (1) `pluginManagement { resolutionStrategy { eachPlugin { useVersion(...) } } }` in `settings.gradle`, which supplies a version per id; and (2) a **version catalog** `[plugins]` alias applied as `alias(libs.plugins.foo)` that carries the version. If neither provides one, Gradle reports that the plugin was requested without a version and cannot resolve it. So 'no version in the script' is only valid when something upstream pins it centrally — which is exactly the point of these mechanisms: keep build scripts clean and versions in one place.

code

groovy · 11 lines
groovy
// build.gradle (no version here)
plugins { id 'com.example.foo' }

// settings.gradle supplies it centrally
pluginManagement {
    resolutionStrategy {
        eachPlugin {
            if (requested.id.id == 'com.example.foo') useVersion('1.4.0')
        }
    }
}

go deeper

for a junior

Name the two central sources (eachPlugin useVersion, catalog alias) and that otherwise it errors.

for a middle

Explain the resolution flow and how to diagnose the 'requested without a version' error.

for a senior

Discuss trade-offs of catalog vs eachPlugin and classpath inheritance from included builds.

for a principal

Standardize where versions live across the org to keep build scripts uniform and auditable.

## The rule Gradle never invents a plugin version. If `plugins { id 'x' }` omits the version, a **central** mechanism must supply it, or resolution fails with an error like *"plugin ... was not found ... it was requested without a version number"*. ## Central sources of a plugin version 1. **Settings eachPlugin hook** — `useVersion` keyed on `requested.id.id`: ``` // settings.gradle pluginManagement { resolutionStrategy { eachPlugin { if (requested.id.id == 'com.example.foo') useVersion('1.4.0') } } } ``` 2. **Version catalog [plugins] table** — declared in `gradle/libs.versions.toml` and applied via alias: ``` # libs.versions.toml [plugins] foo = { id = "com.example.foo", version = "1.4.0" } ``` ``` // build.gradle.kts plugins { alias(libs.plugins.foo) } ``` 3. **Already applied on the classpath** — if a parent/settings plugin or `buildSrc`/included build already put the plugin on the classpath, the script can apply it by id with no version because it's resolved. ## What does NOT supply a version - A bare key in `gradle.properties` is not automatically wired to a plugin id (you'd have to read it in a hook). - The Plugin Portal does not default to latest for a versionless request. ## Why omit versions at all? Centralizing versions (catalog or eachPlugin) removes duplication across modules, makes upgrades a one-line change, and prevents drift. Build scripts read more cleanly: they declare *what* plugin, not *which version*. ## Diagnosing failures If you get a 'requested without a version number' error, check: is there an eachPlugin useVersion for this id? Is there a catalog alias? Is the relevant repository declared in `pluginManagement.repositories`? Missing any of these is the usual cause.

  • What error do you get if no central source pins a versionless plugin request?
    Gradle fails resolution with a message stating the plugin was requested without a version number and could not be found.
  • Does putting fooVersion=1.4.0 in gradle.properties alone fix a versionless request?
    No — a properties key is not auto-bound to a plugin id; you must read it inside an eachPlugin useVersion call (or use a catalog) for it to take effect.

saying these in an interview costs you the question

  • Believing Gradle defaults a versionless plugin to the latest available.
  • Thinking a gradle.properties entry automatically binds to a plugin id.
  • Not knowing the version catalog is a valid central source.

context