What is path sensitivity in Gradle, and why does it matter for up-to-date checks and the build cache?
answer
- fingerprint = path view + content hash
- ABSOLUTE busts cross-machine cache
- RELATIVE strips checkout location
- NAME_ONLY ignores directory
- least sensitive that's still correct
basics
~20 sPath sensitivity tells Gradle whether a file input's path (not just its content) is part of the cache key. Choosing RELATIVE or NAME_ONLY instead of ABSOLUTE lets the same content reuse cached results across different machines or directories.
solid answer
~40 sWhen Gradle decides whether a task is up-to-date or can be loaded from cache, it computes a fingerprint of each file input. Path sensitivity controls **which part of each file's path** enters that fingerprint. With `@PathSensitive(ABSOLUTE)`, moving the project to a different directory or running on another machine changes every path and busts the cache. With `RELATIVE` only the path relative to the input root matters; with `NAME_ONLY` only the file name; with `NONE` only the content. Choosing the least sensitive option that is still **correct for the task** maximizes up-to-date and cache hits — especially for a shared remote cache where source trees live at different absolute paths on CI vs. developer machines. The trade-off is correctness: if a task genuinely depends on where a file sits, weakening sensitivity produces wrong reuse.
code
kotlin · 6 lines// Annotation form on an input property of a task type you consume/configure
abstract class TransformTask : DefaultTask() {
@get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE)
abstract val sources: ConfigurableFileCollection
}go deeper
Know that path sensitivity decides whether a file's path is part of the cache key, and that ABSOLUTE hurts cross-machine reuse.
Explain all four modes, when each is correct, and the up-to-date vs. remote-cache implications of each.
Discuss the correctness boundary — choosing the least-sensitive-but-still-correct mode — and how misuse causes silent wrong reuse.
Frame path sensitivity as a lever in an org-wide cache-hit-rate strategy across heterogeneous checkout paths, and the governance needed to prevent unsafe relaxations.
## The problem path sensitivity solves Gradle avoids redoing work by **fingerprinting** task inputs. Before running a task it captures a snapshot of each input file: its identity (some view of its path) plus a content hash. If the new fingerprint equals the last successful run's fingerprint, the task is **UP-TO-DATE** and skipped; if a matching fingerprint exists in the (local or remote) **build cache**, the outputs are unpacked instead of recomputed. The key question is: **does the file's path belong in the fingerprint, and if so, how much of it?** That is path sensitivity. It is declared with `@PathSensitive(PathSensitivity.X)` on a `@InputFiles`/`@InputDirectory`/`@Classpath`-style property, or via runtime normalization rules. ## The four modes - `PathSensitivity.ABSOLUTE` — the full absolute path is part of the key. Any move of the project, or a different checkout location on another machine, changes the key. Almost never what you want for cacheable work; it kills cross-machine cache hits. - `PathSensitivity.RELATIVE` — only the path **relative to the input root** matters. `src/main/java/A.java` fingerprints the same regardless of where the repo is checked out. This is the sensible default for most source/resource inputs. - `PathSensitivity.NAME_ONLY` — only the file **name** matters, not its directory. Two files named `config.txt` in different folders fingerprint identically (given equal content). - `PathSensitivity.NONE` — only **content** matters; path is ignored entirely. Use when the task processes file contents and is indifferent to where they live (e.g. concatenating a set of files). ## Why it changes cache/up-to-date behavior A task is reused only when its complete input fingerprint matches. ABSOLUTE paths embed machine- and checkout-specific data, so a remote cache populated by CI yields **zero** hits for a developer whose repo lives elsewhere. Relaxing to RELATIVE strips that machine-specific noise, so identical content + identical relative layout reuses results. Going further to NAME_ONLY/NONE strips even more, but each relaxation must be **safe** for the task's semantics. ## Correctness boundary The rule of thumb: pick the **least** sensitive mode that still distinguishes inputs the task actually cares about. If renaming or relocating a file would legitimately change the output, you must NOT relax past the level that captures that difference. Over-relaxing produces silent wrong reuse — far worse than a cache miss. ```kotlin // Declaring the consumed input with a normalization tasks.register<MyProcessTask>("process") { // sources fingerprinted by their path relative to the source set root source.from(layout.projectDirectory.dir("src/main/resources")) } ``` For inputs you wire on existing task types, you usually get RELATIVE-ish defaults (e.g. source sets), but when authoring your own consuming wiring you choose the mode that matches reality.
- Why is ABSOLUTE almost always wrong for a shared remote cache?Because the absolute checkout path differs between CI and each developer's machine, so identical content produces different cache keys and you get no cross-machine hits.
- What's the danger of always picking NONE to maximize hits?If the task's output actually depends on file paths or names, NONE makes Gradle reuse stale outputs incorrectly — a correctness bug that's hard to spot.
Think of fingerprinting like labeling moving boxes. ABSOLUTE writes the full street address on every box, so the labels never match after you move. RELATIVE just writes the room name (kitchen, bedroom) — the same regardless of the house. NONE labels only by contents, ignoring rooms entirely.
saying these in an interview costs you the question
- Claiming path sensitivity changes the content hash itself (it changes which path info joins the hash, not the hashing of bytes).
- Saying RELATIVE means 'relative to the project root' in all cases — it's relative to the input/source root being fingerprinted.
- Assuming weaker sensitivity is always safe to flip on for more hits.