Your convention plugin calls `versionCatalogs.named("libs")` and it throws because the catalog isn't named `libs`, or a second catalog exists. How do you reliably target the right catalog from inside the plugin?
answer
- named() = exact-name lookup
- default name is 'libs'
- UnknownDomainObjectException if absent
- catalogNames to inspect/guard
- multiple catalogs each named separately
basics
~10 snamed(name) must match the catalog's declared name exactly. If you have multiple or a custom name, pass that name; to be defensive, check catalogNames/find(name) first, or iterate, instead of assuming "libs".
solid answer
~40 s`VersionCatalogsExtension.named("libs")` resolves the catalog whose name is exactly `libs` — the default for `gradle/libs.versions.toml`. If a project declares the catalog under another name (e.g. `from(files(...))` as `"deps"`) or defines several catalogs, `named("libs")` will throw `UnknownDomainObjectException`. To be robust in a shared plugin, don't hardcode blindly: you can inspect `extension.catalogNames` (the set of registered names) and pick the right one, or guard with a clear failure message. Using the conventional default `libs` everywhere is the simplest contract, but a convention plugin shipped to many builds should fail with an actionable message ("expected a 'libs' catalog") rather than an opaque exception. Multiple catalogs (e.g. `libs` plus a `tools` catalog) each get their own accessor and their own `named(...)` entry.
code
kotlin · 6 linesval ext = project.extensions.getByType<VersionCatalogsExtension>()
require("libs" in ext.catalogNames) {
"This convention plugin needs a 'libs' catalog; available: ${ext.catalogNames}"
}
val libs = ext.named("libs")
val tools = if ("tools" in ext.catalogNames) ext.named("tools") else nullgo deeper
Know that named("libs") targets the default catalog and the name must match.
Handle a missing/renamed catalog by checking catalogNames and failing with a clear message; know multiple catalogs are independent.
Treat the catalog name as part of a shared plugin's contract and validate it defensively for builds you don't control.
Define an org convention (always libs, plus optional named catalogs) and document the plugin's catalog contract so consuming teams can satisfy it predictably.
## How catalogs are named The default catalog is `libs`, auto-created from `gradle/libs.versions.toml`. You can declare additional or custom-named catalogs in settings: ```kotlin // settings.gradle.kts dependencyResolutionManagement { versionCatalogs { create("libs") { from(files("gradle/libs.versions.toml")) } create("tools") { from(files("gradle/tools.versions.toml")) } } } ``` Each catalog gets its own type-safe accessor (`libs.*`, `tools.*`) in scripts, and each is a distinct entry in `VersionCatalogsExtension`. ## What named() does and how it fails ```kotlin val extension = project.extensions.getByType<VersionCatalogsExtension>() val libs = extension.named("libs") // throws UnknownDomainObjectException if no 'libs' ``` `named(name)` is an exact-name lookup. If the project's catalog is called `deps`, or only `tools` exists, `named("libs")` throws. In a convention plugin distributed across many builds you can't always assume the name. ## Defensive strategies ```kotlin val ext = project.extensions.getByType<VersionCatalogsExtension>() require("libs" in ext.catalogNames) { "Convention plugin requires a 'libs' version catalog; found: ${ext.catalogNames}" } val libs = ext.named("libs") ``` - `catalogNames` exposes the registered set, so you can check before calling `named`. - Provide an actionable error so consumers know to declare/rename the catalog. - For multiple catalogs, call `named("libs")` and `named("tools")` separately — they don't merge. ## Practical guidance For a single-team monorepo, standardizing on the default `libs` and calling `named("libs")` is perfectly fine. The defensive checks matter most when a convention plugin is published and applied in builds you don't fully control, where the catalog name is part of the plugin's implicit contract.
- What exception does `named("libs")` throw when no such catalog exists?An `UnknownDomainObjectException` — the standard Gradle error for looking up a missing named domain object. Wrapping it with a `require`/clear message makes the failure actionable for consumers.
- If a build has both `libs` and `tools` catalogs, how do you read both?Call `named("libs")` and `named("tools")` separately — each catalog is independent and isn't merged. Their accessors and `find*` lookups are scoped to that catalog.
saying these in an interview costs you the question
- Assuming there is always exactly one catalog named `libs`.
- Letting `named` throw an opaque UnknownDomainObjectException instead of a message that tells the consumer what to do.
- Believing multiple catalogs merge into one namespace.