skip to content

A teammate's `build.gradle.kts` has no autocompletion for `implementation(...)` and `java { }` won't compile. How do you diagnose and fix the missing type-safe accessors?

level: seniorimportance: should knowfreq 45%

answer

  1. applied via plugins {} in THIS script?
  2. apply() / buildscript classpath / root subprojects = no accessors
  3. apply false = declared not applied
  4. IDE reload Gradle project
  5. convention plugin = durable fix
  6. generic API as workaround

basics

~20 s

Check that the relevant plugin is applied via plugins {} (not apply() or only in the root's subprojects {}), re-import the Gradle project in the IDE, and fall back to the generic API (configurations.getByName, extensions.configure<T>) where accessors can't be generated.

solid answer

~50 s

Walk the usual root causes. First, **how is the plugin applied?** Accessors only exist for plugins applied via `plugins {}` in *this* script; `apply(plugin = ...)`, `buildscript { classpath }`, or a plugin applied to the project only from the root's `subprojects {}`/`allprojects {}` yield no accessors here. Fix by declaring the plugin in the subproject's own `plugins {}`, ideally through a convention plugin. Second, **`apply false`** in the script means the plugin is declared but not applied — no accessors. Third, **stale IDE model**: accessors are generated during model build, so after editing `plugins {}` you must re-import/sync Gradle; IntelliJ sometimes shows phantom errors until sync. Fourth, **script kind**: `settings.gradle.kts` and `init.gradle.kts` have different accessor sets. As an immediate, plugin-agnostic workaround, use the generic API: `configurations.getByName("implementation")`, `extensions.configure<JavaPluginExtension> { }`, `tasks.named("jar")` — always available regardless of accessor generation.

code

kotlin · 9 lines
kotlin
// buildSrc/src/main/kotlin/myteam.java-conventions.gradle.kts
plugins { `java-library` }

java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } }

// any module: gets implementation(...)/api(...) accessors
// build.gradle.kts
plugins { id("myteam.java-conventions") }
dependencies { implementation("com.google.guava:guava:33.0.0-jre") }

go deeper

for a junior

Suspect the plugin isn't in plugins {}; try an IDE Gradle re-sync.

for a middle

Distinguish apply() vs plugins {}, spot apply false, and use the generic API to unblock.

for a senior

Diagnose cross-project application, recommend convention plugins, and verify via CLI tasks/dependencies vs IDE sync.

for a principal

Drive a convention-plugin strategy so accessor availability is uniform across all modules and onboarding-friendly.

## Diagnostic checklist ### 1. Is the plugin applied via `plugins {}` in *this* script? Accessors are generated only from plugins applied through the `plugins {}` block of the script that wants them. Common misses: - `apply(plugin = "java")` — runs in the compiled body, too late. - `buildscript { dependencies { classpath(...) } }` + `apply` — legacy classpath path, no accessors. - Plugin applied to subprojects from the **root** script via `subprojects { apply(plugin=...) }` — the subproject's own `build.gradle.kts` gets no accessors because, at its compile time, Gradle doesn't see that the root will apply the plugin. **Fix:** apply the plugin in the subproject's own `plugins {}`. Best practice: create a **convention plugin** (a precompiled script plugin in `buildSrc` or an included `build-logic` build) that applies the plugin, and have each module do `plugins { id("myteam.java-conventions") }`. Convention plugins themselves get accessors because *they* apply the underlying plugin via `plugins {}`. ### 2. `apply false` ```kotlin plugins { id("org.springframework.boot") version "3.2.0" apply false } ``` This declares the version (e.g. for subprojects) but does **not** apply it here, so no `springBoot { }` accessor in this script. ### 3. Stale IDE / model not rebuilt Accessors are produced during Gradle's model/configuration build. After editing `plugins {}`, IntelliJ may still show red until you **Reload Gradle Project**. A clean check: run `./gradlew help` or `./gradlew tasks` from the CLI — if that succeeds but the IDE is red, it's an IDE sync issue. ### 4. Wrong script type `settings.gradle.kts` exposes `Settings`-level accessors (e.g. `dependencyResolutionManagement { }`), not `Project` ones; `init.gradle.kts` is different again. Expecting `implementation(...)` there is a category error. ### 5. Plugin genuinely doesn't contribute it No `java`/`java-library` ⇒ no `implementation`/`api`. Confirm with `./gradlew :module:dependencies` or by checking the plugin's docs. ## Immediate workaround: generic API ```kotlin // always available, no accessors needed configurations.getByName("implementation").dependencies.add( dependencies.create("com.google.guava:guava:33.0.0-jre") ) extensions.configure<JavaPluginExtension> { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } } tasks.named<Jar>("jar") { archiveBaseName.set("app") } ``` ## Verification - `./gradlew :module:tasks` / `:module:dependencies` to confirm the plugin's contributions exist. - IDE: File → Sync/Reload All Gradle Projects. - Grep for `apply(plugin` and stray `apply false` in the offending script. ## Root-cause summary Missing accessors ≈ "the plugin isn't applied via `plugins {}` in this exact script, or the IDE hasn't re-synced." The durable fix in multi-module builds is convention plugins so every module applies its plugins the same way and gets consistent accessors.

  • Why does applying the plugin from the root's `subprojects {}` not fix the subproject's accessors?
    At the subproject script's compile time Gradle doesn't know the root will later apply the plugin to it, so no accessors are generated. The subproject must apply it via its own `plugins {}` (e.g. a convention plugin).
  • How do convention plugins restore accessors cleanly?
    A precompiled script plugin applies the underlying plugins via its own `plugins {}` block and gets accessors internally; modules then apply the convention plugin via `plugins {}`, inheriting consistent, applied behavior — though within a module you still configure via the convention's exposed extensions or generic API.
  • If the CLI build succeeds but the IDE shows errors, what's the likely cause?
    A stale IDE Gradle model. Reload/sync the Gradle project so it regenerates accessors; the build itself is fine.

saying these in an interview costs you the question

  • Jumping to 'reinstall Gradle' instead of checking how the plugin is applied.
  • Believing root-level `subprojects { apply(...) }` gives subprojects accessors.
  • Forgetting the generic API exists as an immediate unblock.

context