skip to content

Explain the different task outcomes Gradle reports during execution (UP-TO-DATE, SKIPPED, NO-SOURCE, FROM-CACHE) and what triggers each.

level: seniorimportance: should knowfreq 40%

answer

  1. (none)=ran, UP-TO-DATE=unchanged
  2. FROM-CACHE=build cache restore
  3. SKIPPED=onlyIf false or -x
  4. NO-SOURCE=empty source inputs
  5. FAILED=action threw

basics

~20 s

No label = the action ran. UP-TO-DATE = inputs/outputs unchanged. FROM-CACHE = outputs pulled from the build cache. SKIPPED = an onlyIf {} predicate was false (or the task was excluded). NO-SOURCE = the task's declared source inputs were empty.

solid answer

~40 s

During Execution each task gets an **outcome** printed beside it (when run with `--console=plain`/`--info`): - **(none)** — the task's actions executed normally. - **UP-TO-DATE** — incremental build determined inputs and outputs are unchanged and outputs exist, so the action was skipped. - **FROM-CACHE** — a `@CacheableTask` had a matching entry in the local/remote **build cache**; outputs were restored instead of being recomputed. - **SKIPPED** — an `onlyIf {}` predicate returned `false`, or the task was excluded via `-x`/`--exclude-task`. The decision is made at execution start. - **NO-SOURCE** — the task declared **source** inputs (e.g. `@SkipWhenEmpty` / `@InputFiles` marked as sources) but they resolved to *empty*, so there was nothing to process. These outcomes drive the build summary and are how you diagnose whether a task did real work, was avoided, or was deliberately skipped.

code

bash · 5 lines
bash
gradle build --info
# > Task :compileJava NO-SOURCE     # no .java sources
# > Task :processResources UP-TO-DATE
# > Task :jar FROM-CACHE            # restored from build cache
# > Task :test SKIPPED              # because: gradle build -x test

go deeper

for a junior

Recognize that UP-TO-DATE means skipped-because-unchanged and (no label) means it ran.

for a middle

Differentiate UP-TO-DATE, SKIPPED, and NO-SOURCE and what triggers each.

for a senior

Explain FROM-CACHE prerequisites and use these outcomes to diagnose build performance from --info output.

for a principal

Use outcome telemetry (build scans) across a fleet to spot cache misses and tasks that fail to go UP-TO-DATE/FROM-CACHE.

## Outcomes are per-task labels When Gradle executes the graph, it labels each task with the reason it did or didn't do work. Knowing them is essential for diagnosing slow builds and unexpected behavior. ## The outcomes ### Executed (no label) The task ran its `@TaskAction`/`doFirst`/`doLast`. Shown plainly, e.g. `> Task :compileJava`. ### UP-TO-DATE Incremental build: declared inputs and outputs match the previous run and outputs still exist, so actions are skipped. (See up-to-date checking.) ### FROM-CACHE For tasks annotated `@CacheableTask` (or with caching enabled), Gradle computes a **cache key** from inputs + implementation. If a matching entry exists in the local or a remote **build cache**, it **restores** the outputs rather than recomputing them. Requires `org.gradle.caching=true`. ### SKIPPED Produced by: - `onlyIf { predicate }` returning `false`. - Excluding the task: `gradle build -x test`. The task is in the graph but deliberately not executed. ```kotlin tasks.register("publishDocs") { onlyIf { project.hasProperty("release") } // SKIPPED unless -Prelease doLast { /* ... */ } } ``` ### NO-SOURCE When a task's **source** inputs (an `@InputFiles` property also marked `@SkipWhenEmpty`) are empty — e.g. `compileJava` with no `.java` files — Gradle reports `NO-SOURCE` and skips. It is distinct from UP-TO-DATE (which means *unchanged*, not *absent*). ## Quick reference | Outcome | Trigger | |---|---| | (none) | actions ran | | UP-TO-DATE | inputs+outputs unchanged, outputs exist | | FROM-CACHE | matching build-cache entry restored | | SKIPPED | `onlyIf` false or `-x` exclusion | | NO-SOURCE | declared source inputs empty | | FAILED | task action threw | ## Why it matters Reading these in `--info` output tells you exactly why a build was fast or slow and whether incremental/caching is actually working, or whether a task you expected to run was silently skipped.

  • What's the difference between UP-TO-DATE and NO-SOURCE?
    UP-TO-DATE means inputs/outputs are unchanged since last run; NO-SOURCE means the task's declared source inputs are empty, so there is simply nothing to process.
  • What must be true for FROM-CACHE to appear?
    The build cache must be enabled (`org.gradle.caching=true`), the task must be cacheable, and a matching cache entry (by input/implementation key) must exist locally or remotely.
  • How do you make a task SKIPPED conditionally?
    Add `onlyIf { condition }`; when the predicate is false the task is reported SKIPPED and its actions don't run.

saying these in an interview costs you the question

  • Confusing NO-SOURCE with UP-TO-DATE.
  • Saying FROM-CACHE works without enabling the build cache or marking the task cacheable.
  • Claiming SKIPPED removes the task from the graph (it stays in the graph, just isn't executed).

context