What do `isCanBeResolved` and `isCanBeConsumed` mean, and what is wrong with a configuration where both are true?
answer
- canBeResolved = compute for my build
- canBeConsumed = expose to others
- bucket = both false
- both true = deprecated legacy
- leakage + ambiguous selection
basics
~10 sisCanBeResolved = Gradle can compute its artifacts for this build; isCanBeConsumed = other projects can depend on it. Both true is the deprecated legacy 'do-everything' role and should be split.
solid answer
~40 sThe two booleans encode a configuration's role. `isCanBeResolved = true` means the configuration is **resolvable** — Gradle may run dependency resolution and variant selection to turn it into concrete artifacts for *this* build (e.g. a classpath). `isCanBeConsumed = true` means it is **consumable** — it is a variant *other* projects can pick up when they depend on this project. A dependency-scope bucket has both **false** (declaration only). Having **both true** is the legacy 'do-everything' configuration: it tries to be the place you declare, the thing you resolve, and the variant you expose all at once. That causes ambiguous variant selection, accidental leakage of resolution-only dependencies into the published variant, and Gradle deprecation warnings. The fix is to split it into separate role-locked configurations using `dependencyScope`/`resolvable`/`consumable` and wire them with `extendsFrom`.
code
kotlin · 5 linesconfigurations.all {
check(!(isCanBeResolved && isCanBeConsumed)) {
"$name is a deprecated dual-role configuration; split it into resolvable + consumable"
}
}go deeper
Define each flag in one sentence and note buckets have both false.
Map the flags to the three roles and identify which standard configs fall where.
Explain why both-true causes leakage and ambiguous selection, and how to refactor with role factories.
Treat dual-role configurations as tech debt; enforce role correctness via shared plugins and build-scan/lint checks across the org.
## The two flags Every `Configuration` exposes: - `isCanBeResolved` — may Gradle *resolve* this into artifacts for the current build? Resolving runs graph resolution + variant selection. - `isCanBeConsumed` — may *other* projects depend on this as a variant when they declare a project dependency? ## The role table | Role | canBeResolved | canBeConsumed | Example | |------|---------------|---------------|---------| | Dependency-scope (bucket) | false | false | `implementation`, `api` | | Resolvable | true | false | `compileClasspath`, `runtimeClasspath` | | Consumable | false | true | `apiElements`, `runtimeElements` | | Legacy (deprecated) | true | true | old hand-rolled configs | ## Why both-true is bad A both-true configuration: - **Leaks**: dependencies you only needed to resolve locally get exposed to consumers (or vice versa), polluting the published variant. - **Ambiguous selection**: when it both produces and requests variants, attribute matching becomes confusing and error-prone. - **Deprecated**: Gradle warns and is removing the mutable both-true path; future versions reject it. ## Inspecting and fixing ```kotlin configurations.all { if (isCanBeResolved && isCanBeConsumed) { logger.warn("$name has a deprecated dual role") } } ``` The fix is to separate concerns: ```kotlin val bucket = configurations.dependencyScope("feature") val resolve = configurations.resolvable("featurePath") { extendsFrom(bucket.get()) } val expose = configurations.consumable("featureElements") { extendsFrom(bucket.get()) } ``` ## Takeaway The flags *are* the role. Keep exactly one of them true (or both false for a bucket); both-true is legacy and should be refactored into role-locked configurations.
- What practical problem arises if a published consumable configuration is also resolvable?Dependencies you only added to resolve a local classpath can leak into the variant other projects consume, giving consumers unexpected transitive dependencies and breaking the intended API surface.
- How do you migrate a legacy both-true configuration?Create a dependency-scope bucket for declarations, a resolvable configuration for local resolution, and a consumable configuration for exposure, each wired with extendsFrom and carrying the correct attributes — using the role factories.
saying these in an interview costs you the question
- Saying both-true is fine or recommended.
- Conflating 'resolvable' with 'consumable' (computed for me vs exposed to others).
- Thinking the flags are cosmetic rather than driving variant selection and leakage.