skip to content

Up-to-Date Checking

How a task ends up reported as UP-TO-DATE, FROM-CACHE, or NO-SOURCE, and how --info tells you why it ran again. Asked constantly, because 'why does this task always re-run?' is a daily Gradle question.

on this pageshow

questions

5

When you run a Gradle build and see a task labeled UP-TO-DATE in the output, what does that tell you and why did it happen?

level: juniorimportance: must knowfreq 78%

answer

  1. inputs + outputs both unchanged
  2. task skipped, not executed
  3. fingerprint compared to last run
  4. local, not the cache
  5. no-op build is fast

basics

~10 s

UP-TO-DATE means Gradle skipped running the task because its inputs and outputs haven't changed since the last run, so re-executing would produce identical results.

solid answer

~40 s

When a task prints `UP-TO-DATE`, Gradle decided it would be wasteful to run it: nothing it depends on has changed. Gradle tracks each task's declared inputs (source files, properties) and outputs (generated files/dirs). After a build it records a fingerprint of them. On the next run it compares the current fingerprint to the stored one; if both inputs and outputs match, the task is skipped and marked UP-TO-DATE. This is local incremental build behaviour and is what makes a no-op `./gradlew build` fast. It's distinct from FROM-CACHE (output pulled from the build cache) — UP-TO-DATE means the existing outputs in your project are already correct.

code

bash · 9 lines
bash
$ ./gradlew build
> Task :compileJava UP-TO-DATE
> Task :processResources UP-TO-DATE
> Task :classes UP-TO-DATE
> Task :jar UP-TO-DATE
> Task :build UP-TO-DATE

BUILD SUCCESSFUL in 412ms
7 actionable tasks: 7 up-to-date

go deeper

for a junior

Recall that UP-TO-DATE = task skipped because inputs/outputs didn't change. Recognize it in build output.

for a middle

Explain the input/output fingerprint comparison and contrast UP-TO-DATE with a task that simply ran (no annotation).

for a senior

Distinguish UP-TO-DATE (local, already-current) from FROM-CACHE (fetched), and note that undeclared outputs force re-execution.

for a principal

Frame up-to-date checking as the foundation of incremental builds and a prerequisite for reliable caching across a large multi-module codebase.

## What UP-TO-DATE means Gradle is an *incremental* build tool. Every time you run a task, Gradle would prefer **not** to actually execute it if the result would be identical to last time. The mechanism that decides this is **up-to-date checking**. Each task can declare: - **Inputs** — the things that affect its result: source files, input directories, and scalar properties (a version string, a boolean flag). - **Outputs** — the files and directories it produces. ### The decision After a task runs successfully, Gradle stores a fingerprint of its inputs and outputs in the project's `.gradle` directory. On the next invocation, before running the task, Gradle recomputes the current fingerprint and compares: 1. If **inputs unchanged** AND **outputs unchanged** → the task is skipped and the console shows `UP-TO-DATE`. 2. If anything differs → the task executes again (and the console shows nothing after the task name, meaning it ran). ### Reading the outcome With default (lifecycle) logging you only see the *changed* tasks annotated. A task with no annotation **ran**; `UP-TO-DATE` means it was skipped because it was already current. ```text > Task :compileJava UP-TO-DATE > Task :processResources UP-TO-DATE > Task :jar UP-TO-DATE ``` A fully UP-TO-DATE `build` is the fast "nothing changed" case. ### Why it matters This is the core of fast iterative builds: only the tasks whose inputs actually changed re-run. A task is only eligible for up-to-date checking if it **declares** inputs and outputs; a task with no declared outputs always runs. UP-TO-DATE is **local** — it reflects the state of files already on your machine. That distinguishes it from FROM-CACHE, where Gradle had to *fetch* outputs from a (possibly remote) build cache because they weren't present locally.

  • If a task declares no outputs at all, will it ever be UP-TO-DATE?
    No. With nothing to compare, Gradle can't prove the result is still valid, so such a task executes on every run.
  • Does UP-TO-DATE mean the same as FROM-CACHE?
    No. UP-TO-DATE means the correct outputs are already present locally and nothing changed; FROM-CACHE means outputs were missing locally and were fetched from the build cache.

Like a spreadsheet that only recalculates a cell when one of its referenced cells changed — untouched cells keep their old value instead of being recomputed.

saying these in an interview costs you the question

  • Saying UP-TO-DATE means the task 'succeeded last time' — it means inputs/outputs are unchanged this time.
  • Confusing UP-TO-DATE with FROM-CACHE (cache retrieval).
  • Claiming every task can be UP-TO-DATE regardless of whether it declares outputs.

context

open as a page

A teammate complains that a task keeps re-running even though 'nothing changed.' From a consumer's seat, how do you find out why Gradle decided the task was no longer up-to-date?

level: middleimportance: must knowfreq 68%

basics

~10 s

Run the build with --info. For each non-skipped task Gradle prints a reason like 'Input property X has changed' or 'Output file Y has been removed', telling you exactly why it re-executed.

open as a page

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.

level: middleimportance: must knowfreq 70%

basics

~10 s

UP-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.

open as a page

After a build, Gradle prints a line like '9 actionable tasks: 2 executed, 5 up-to-date, 2 from cache'. How do you read this summary, and what would it tell you about your build's incrementality?

level: juniorimportance: should knowfreq 50%

basics

~10 s

It counts actionable tasks by outcome: how many actually ran (executed) versus were skipped as up-to-date or restored from cache. Mostly up-to-date/from-cache means a well-behaving incremental build; many executed means real work was redone.

open as a page

On the same project, the same task can show UP-TO-DATE on one run and FROM-CACHE on another. Explain the difference and when each occurs.

level: seniorimportance: should knowfreq 55%

basics

~20 s

UP-TO-DATE: the correct outputs are already on disk locally and inputs are unchanged, so nothing happens. FROM-CACHE: the outputs are missing locally, so Gradle restores a matching entry from the build cache instead of running the task.

open as a page