A build fails with 'No matching variant ... was found' or 'cannot choose between variants'. How do you diagnose and fix it?
answer
- no matching = zero compatible
- ambiguous = many, no tie-break
- read incompatible-attributes section
- dependencyInsight / outgoingVariants
- fix request or add rule
basics
~20 sRead the error: it lists the attributes you requested versus what each variant offers, marking matches and mismatches. Fix by aligning attributes — request the right Usage/JVM version, or add a compatibility/disambiguation rule so one variant is selected.
solid answer
~50 sThese are variant-selection failures. **No matching variant** means no producer variant was compatible with the consumer's requested attributes; **cannot choose between variants** (ambiguous) means several were compatible and nothing broke the tie. Gradle's message is the primary diagnostic: it prints the requested attributes and, per candidate variant, which attributes were *compatible*, *incompatible*, or *unmatched/unspecified*. Look for the attribute that is incompatible or missing. Common causes: requesting a `TargetJvmVersion` higher than any published variant supports; a library not publishing a needed variant (e.g. no Gradle Module Metadata so only a plain jar exists); or two variants that differ only in an attribute your consumer didn't constrain. Fixes: lower or correct the requested attribute, add the missing attribute to the consumer config, register a compatibility/disambiguation rule, or use `--info`/the `dependencyInsight` task to see the resolved variant. The `outgoingVariants` task on the producer shows what it actually publishes.
code
bash · 5 lines./gradlew dependencyInsight \
--configuration runtimeClasspath \
--dependency com.example:lib
./gradlew outgoingVariantsgo deeper
Know the error exists and that reading the message (requested vs available attributes) is step one.
Distinguish no-matching vs ambiguous, read the incompatible-attributes section, and use dependencyInsight/outgoingVariants to fix.
Systematically isolate the offending attribute, decide between changing the request vs adding schema rules, and avoid blunt forces/excludes.
Establish team conventions for diagnosing variant failures, build-scan usage, and when to push fixes upstream into a library's metadata.
## Two distinct failures ### No matching variant For some attribute, **zero** of the target's variants are compatible with what the consumer requested. The component exists, but nothing satisfies the constraints. ### Cannot choose between variants (ambiguous) Multiple variants are compatible and there is no disambiguation rule (or extra requested attribute) to pick one. ## Reading the message Gradle prints a structured report. For each candidate variant it lists attributes under headings like: - *Compatible attributes* — matched or compatibly-resolved. - *Incompatible attributes* — the consumer asked X, the variant has Y, and the rule rejected it. **This is usually the culprit.** - *Other attributes* — present on one side only (unspecified on the other), which is allowed but informative. ## Diagnostic tooling - **`./gradlew dependencyInsight --configuration compileClasspath --dependency com.example:lib`** shows how a dependency resolved and the selected variant. - **`./gradlew outgoingVariants`** on the *producer* lists every variant it publishes with attributes and artifacts — confirms whether the variant you need even exists. - **`./gradlew resolvableConfigurations`** shows what each consumer configuration requests. - **`--info`** / build scans add detail. ## Typical causes and fixes | Symptom | Likely cause | Fix | |---|---|---| | No matching variant, JVM mismatch | Requested `TargetJvmVersion` higher than published | Lower the toolchain/target, or get the library to publish a matching variant | | No matching variant on a plain library | No Gradle Module Metadata, only a POM/jar | Usually resolves as a fallback jar; if you force attributes, relax them | | Ambiguous | Two variants differ only by an attribute you didn't set | Add that attribute to the consumer config, or register a disambiguation rule | | Custom attribute unmatched | Forgot to set the consumer attribute or register a rule | Set the attribute and/or add compatibility/disambiguation rules in `attributesSchema` | ## Example ```bash # See exactly which variant was chosen (or why it failed) ./gradlew dependencyInsight \ --configuration runtimeClasspath \ --dependency com.example:lib # On the producing project, list what it actually publishes ./gradlew outgoingVariants ``` The discipline: trust the error report, find the *one* incompatible/missing attribute, then either change the request or the schema/rules rather than guessing.
- Which task tells you what variants a library actually publishes?On the producing project, `./gradlew outgoingVariants` lists each consumable variant with its attributes and artifacts; for an external lib you inspect its published Gradle Module Metadata.
- You request TargetJvmVersion 21 but the only variant targets 17 — why does it fail and how do you fix it?JVM-17 bytecode is fine on 21, but the variant *declares* it targets 17 while you constrained 21, and the compatibility rule treats a higher requested version as needing >=; lower your requested target or use a toolchain matching what's published.
saying these in an interview costs you the question
- Blindly adding `force` or excluding deps instead of reading which attribute mismatched.
- Assuming the library is broken when the consumer simply requested an unsatisfiable attribute.