A consumer build picks an unexpected variant or fails with 'no variants match' for a dependency. How does Gradle Module Metadata factor into diagnosing this?
answer
- variant-aware matching needs exactly one match
- no-match vs ambiguity errors
- dependencyInsight shows requested vs available attrs
- read the .module for ground truth
- fix via component metadata rules / capabilities
basics
~20 sGMM exposes the published variants and their attributes. When resolution fails, you compare the consumer's requested attributes against each variant's attributes — usually with dependencyInsight or by reading the .module file — and reconcile the mismatch via attributes, capabilities, or a component metadata rule.
solid answer
~40 sVariant selection failures almost always trace back to attribute mismatches that GMM makes visible. The consumer configuration requests a set of attributes (usage, libraryelements, jvm.version, etc.); resolution must find exactly one matching variant in the dependency's GMM. If none match, you get 'no variants match'; if several match equally, an ambiguity error. Diagnose by running `gradle dependencyInsight --configuration runtimeClasspath --dependency foo`, which prints requested vs. available attributes, and by inspecting the published `.module` to see the real variant set and capabilities. Fixes include setting/aligning a consumer attribute, declaring a `requireCapability`, or, when the published metadata is wrong, patching it with a **component metadata rule** (`withVariant { ... }`) — without forcing the publisher to republish. If the library is POM-only, there's no rich variant info to match, which itself is often the root cause.
code
bash · 4 lines# Show why a variant was (not) selected — requested vs available attributes:
gradle dependencyInsight \
--configuration runtimeClasspath \
--dependency com.acme:libgo deeper
Recognize that the error is about variant/attribute matching and that dependencyInsight helps.
Use dependencyInsight and read the .module to compare requested vs available attributes.
Apply component metadata rules and capability resolution to fix mismatches without republishing.
Treat recurring mismatches as an org-wide attribute-schema/publishing-policy problem and standardize platforms and GMM publication.
## Why GMM is central to diagnosis Gradle resolves by **variant-aware matching**: a consumer configuration declares requested attributes, and Gradle must select exactly one variant of each dependency whose attributes are compatible. GMM is where those producer-side variants and attributes are declared, so it is the ground truth you inspect when selection misbehaves. ## The two failure shapes 1. **No variants match** — no published variant satisfies the requested attributes (e.g. consumer wants `org.gradle.jvm.version=11` but the library only publishes a JDK 17 variant). 2. **Ambiguity** — more than one variant matches equally and Gradle can't disambiguate. ## Diagnostic tools - `gradle dependencyInsight --configuration runtimeClasspath --dependency com.acme:lib` — shows the requested attributes and the candidate variants with their attributes, plus *why* each was rejected. - Reading the published `.module` directly (it's in the cache under the Gradle user home, or fetchable from the repo) reveals the actual variant names, attributes, capabilities, and files. - `gradle dependencies` / build scans for the broader graph. ## Fixes ```kotlin // 1. Patch wrong/missing attributes on a published variant without republishing: dependencies { components { withModule("com.acme:lib") { withVariant("runtime") { attributes { attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, 11) } } } } } ``` - **Component metadata rules** (`components { withModule(...) { ... } }`) let you add/override attributes, declare capabilities, or fix dependencies on third-party GMM/POM metadata locally. - **Capabilities**: if two modules provide the same capability (e.g. `groovy` vs `groovy-all`), you resolve the conflict by choosing one via `resolutionStrategy.capabilitiesResolution` or `requireCapability`. ## The POM-only trap If the dependency publishes **no** `.module`, Gradle synthesizes minimal variants from the POM. That's a frequent root cause of 'no variants match' for niche attributes — the rich info simply isn't there, and the fix is a component metadata rule that injects the missing attributes. ## Architectural takeaway At scale, recurring variant mismatches signal an attribute-schema misalignment across an org's libraries — best addressed by standardizing platform/attribute conventions and publishing all internal libs with GMM.
- Which command shows requested vs available attributes for a failing dependency?`gradle dependencyInsight --configuration <cfg> --dependency <group:name>` prints the requested attributes and each candidate variant with the rejection reason.
- The library is POM-only and a niche attribute won't match — what's the fix?Add a component metadata rule (`components { withModule(...) { withVariant(...) { attributes { ... } } } }`) to inject the missing attribute locally, without republishing the artifact.
- What causes an 'ambiguity' (rather than 'no match') error?Two or more published variants match the requested attributes equally, so Gradle cannot pick one; you disambiguate by adding a discriminating attribute or capability.
saying these in an interview costs you the question
- Jumping to forceful version overrides instead of reading the actual variant attributes in the .module.
- Assuming you must get the publisher to republish — component metadata rules fix third-party metadata locally.