If you apply a plugin by id in build.gradle without a version, where does Gradle get the version from?
answer
- Gradle never invents a version
- eachPlugin useVersion OR catalog alias
- else 'requested without a version' error
- gradle.properties not auto-wired
- central = clean scripts + no drift
basics
~10 sFrom 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 sA 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// 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
Name the two central sources (eachPlugin useVersion, catalog alias) and that otherwise it errors.
Explain the resolution flow and how to diagnose the 'requested without a version' error.
Discuss trade-offs of catalog vs eachPlugin and classpath inheritance from included builds.
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.