skip to content

Walk me through the common categories of problems you see in a configuration-cache report and what each generally points to.

level: middleimportance: should knowfreq 42%

answer

  1. non-serializable / unsupported type
  2. Task.project / Project access at execution time
  3. untracked inputs: sys prop / env / file at config time
  4. declared incompatible task/plugin
  5. category -> fix family

basics

~20 s

Common categories: reading a non-serializable value into cached state, accessing the Project (or task.project) at execution time, reading system properties / env vars / files at configuration time, and using unsupported types. Each category points at a different rule the build logic broke.

solid answer

~40 s

Configuration-cache problems cluster into a few recurring categories shown in the report. **Unsupported / non-serializable state**: a task field or graph object can't be serialized into the cache (e.g. holding a `Configuration`, `Project`, `Gradle`, or a closure capturing live objects). **Execution-time access to live build model**: code calls `Task.project`, `task.getProject()`, or otherwise reaches the `Project`/`Gradle` object while a task runs, which is forbidden because that state isn't reconstructed from the cache. **Untracked configuration inputs**: reading `System.getProperty`, environment variables, or files at configuration time without going through Gradle's providers, so Gradle warns the input isn't tracked for cache invalidation. **Plugin/core incompatibility**: a task or plugin explicitly declared incompatible. Reading the category tells you the fix family — replace live references with `Provider`/`Property`, inject services, or use `providers.systemProperty(...)` so inputs are tracked.

code

kotlin · 9 lines
kotlin
// Execution-time Project access (a problem) ...
tasks.register("bad") {
    doLast { println(project.version) } // reaches Project at execution
}
// ... fixed by capturing at configuration time
val ver = project.version.toString()
tasks.register("good") {
    doLast { println(ver) }
}

go deeper

for a junior

Name a couple of categories (non-serializable state, Project at execution time) and that each maps to a rule that was broken.

for a middle

Cover the main categories and the corresponding fix family (Provider/Property, providers.systemProperty, service injection).

for a senior

Connect categories to the config/execution split and input tracking; reason about which fix preserves cache correctness vs. just silencing.

for a principal

Discuss prioritizing categories across a large build, pushing fixes upstream into shared plugins, and policy for tolerating vs. eliminating each category.

## Why categories exist The configuration cache stores the configured task graph and replays it later, skipping configuration. For that to be sound, the build must follow rules; each rule violation maps to a **problem category** in the report. Recognizing the category short-cuts you to the fix. ## The recurring categories ### 1. Non-serializable / unsupported types in cached state The cache serializes task state and graph objects. If a task holds a field referencing something that can't be (or shouldn't be) serialized — a `Project`, `Gradle`, `Configuration`, a `Task`, a thread, a live closure — you get a *“cannot serialize”* or *“unsupported type”* problem. Fix: store only plain data or lazy `Provider`/`Property` values; don't capture live build objects. ### 2. Reaching the build model at execution time During execution, the `Project` and `Gradle` objects are not available from the cache. Calls like `task.project`, `project.version`, `project.configurations` *inside a task action* produce *“invocation of 'Task.project' at execution time is unsupported”*. Fix: capture the value you need at configuration time into a `Provider`/`Property`, or inject a service (e.g. `ProjectLayout`, `ProviderFactory`, a `BuildService`). ### 3. Untracked configuration inputs Reading `System.getProperty(...)`, `System.getenv(...)`, or a file directly at configuration time is flagged because the cache can't know to invalidate when that value changes. Fix: use `providers.systemProperty("k")`, `providers.environmentVariable("K")`, or `providers.fileContents(...)` so the read becomes a tracked input. ### 4. Declared incompatibility A plugin or task may be explicitly marked not compatible with the configuration cache (`notCompatibleWithConfigurationCache(...)`), which appears as its own problem entry naming the task. ## Reading the tree Each category entry expands to an ownership chain: build → task → input/field → call site. That chain plus the category name is enough to choose the fix family without guessing. ```kotlin // Untracked input -> tracked // before val flag = System.getProperty("ci") != null // after val flag = providers.systemProperty("ci").isPresent ```

  • Why is reading System.getProperty at configuration time a problem but using providers.systemProperty isn't?
    providers.systemProperty registers the read as a tracked configuration input, so Gradle invalidates the cache when the property changes. A raw System.getProperty is invisible to Gradle, so the cache could serve stale configuration.
  • Is holding a Project reference in a task field always wrong under the config cache?
    Yes for cached builds — Project isn't serializable into the cache and isn't available at execution time. Capture the needed values into Providers/Properties or inject services instead.

saying these in an interview costs you the question

  • Confusing configuration-cache problem categories with build (task-output) cache misses.
  • Suggesting you 'just serialize the Project' — Project is intentionally not cacheable.
  • Claiming any System.getProperty use is fine — at configuration time it's an untracked input.

context