Gradle annotates tasks in the console with outcomes like UP-TO-DATE, FROM-CACHE, NO-SOURCE, and SKIPPED. Walk me through what each of these means.
answer
- no suffix = executed
- UP-TO-DATE = already current locally
- FROM-CACHE = restored from cache
- NO-SOURCE = empty inputs
- SKIPPED = -x or onlyIf false
basics
~10 sUP-TO-DATE = skipped, outputs already current. FROM-CACHE = outputs fetched from the build cache. NO-SOURCE = no input source files to process. SKIPPED = excluded or its onlyIf condition was false.
solid answer
~40 sGradle suffixes each task line with its **outcome**: - **(no suffix)** — the task executed. - **UP-TO-DATE** — skipped; declared inputs and outputs are unchanged, so existing outputs are still valid. - **FROM-CACHE** — outputs were not present locally but a matching entry existed in the build cache, so Gradle restored them instead of running the task (requires caching enabled and a `@CacheableTask`). - **NO-SOURCE** — the task's input source set resolved to *empty* (e.g. `compileJava` with no `.java` files), so there was nothing to do. - **SKIPPED** — the task was explicitly excluded (`-x`) or its `onlyIf {}` predicate returned false. Reading these tells you *why* a build was fast or slow: a wall of UP-TO-DATE/FROM-CACHE is the ideal incremental build; tasks with no suffix are the ones that actually did work.
code
bash · 10 lines$ ./gradlew build --build-cache
> Task :compileJava FROM-CACHE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :compileTestJava NO-SOURCE
> Task :test SKIPPED # ran with -x test or onlyIf{false}
> Task :jar UP-TO-DATE
BUILD SUCCESSFUL in 1s
6 actionable tasks: 1 from cache, 4 up-to-date, 1 skippedgo deeper
Recall the four labels and that all of them (except 'executed') mean the task did little or no work.
Cleanly separate UP-TO-DATE vs FROM-CACHE and NO-SOURCE vs SKIPPED, with a concrete clean-then-build example.
Use the outcome mix to reason about build performance and to spot tasks that should be cacheable but aren't.
Read aggregate outcome ratios across modules/CI to assess incrementality health and guide caching investment.
## Task outcomes in the console When Gradle finishes a task it labels it with an **outcome** that explains what it decided to do. Learning to read these is the fastest way to diagnose build performance. ### The outcomes | Suffix | Meaning | |---|---| | *(none)* | The task **executed** — it actually ran its actions. | | `UP-TO-DATE` | **Skipped.** Declared inputs and outputs are unchanged since the last run, so the existing outputs are still correct. | | `FROM-CACHE` | The outputs were **missing locally** but a matching entry was found in the build cache and **restored**. Requires `org.gradle.caching=true` and a cacheable task. | | `NO-SOURCE` | The task's input source was **empty** — there were no files to act on (e.g. `compileTestJava` with no test sources). | | `SKIPPED` | The task was **deliberately not run** — excluded via `-x`/`--exclude-task`, or its `onlyIf { }` condition evaluated to false. | ### UP-TO-DATE vs FROM-CACHE — the key contrast Both mean "the task didn't really run," but the *reason* differs: - **UP-TO-DATE**: the correct outputs are **already on disk** in your project. Nothing was copied. - **FROM-CACHE**: the outputs were **absent** (clean checkout, after `clean`, or a different machine), so Gradle **fetched** a previously stored copy keyed by the task's input fingerprint. A common real scenario: run `./gradlew clean build` — `compileJava` can be `FROM-CACHE` (outputs were deleted by clean but the cache still had them); run `build` again without cleaning and the same task is now `UP-TO-DATE`. ### NO-SOURCE vs SKIPPED They look similar but aren't: - `NO-SOURCE` = the task *would* run but there's no input to process. - `SKIPPED` = you (or a condition) told Gradle not to run it. ### Where to see them Default lifecycle logging already shows these suffixes. The summary line — e.g. `7 actionable tasks: 2 executed, 3 up-to-date, 2 from cache` — aggregates the same information. ```text > Task :compileJava FROM-CACHE > Task :processResources UP-TO-DATE > Task :compileTestJava NO-SOURCE > Task :test SKIPPED BUILD SUCCESSFUL 5 actionable tasks: 1 from cache, 2 up-to-date, 1 skipped ```
- After `./gradlew clean`, why might compileJava show FROM-CACHE rather than UP-TO-DATE?clean deleted the local outputs, so they're no longer on disk. The build cache still holds a copy keyed by the unchanged input fingerprint, so Gradle restores it: FROM-CACHE.
- What's the difference between NO-SOURCE and SKIPPED?NO-SOURCE means the task had no input files to process. SKIPPED means it was excluded with -x or an onlyIf predicate returned false.
saying these in an interview costs you the question
- Treating FROM-CACHE and UP-TO-DATE as the same outcome.
- Thinking NO-SOURCE indicates an error — it's a normal, successful skip.
- Believing a task with no suffix was somehow skipped — no suffix means it executed.