What happens when a task fails during execution, and how does `--continue` change Gradle's behavior?
answer
- default = fail-fast, non-zero exit
- --continue runs all independent tasks
- skips only failed task's dependents
- aggregates all failures at end
- finalizedBy runs even on failure
basics
~20 sBy default Gradle stops at the first task failure (fail-fast): no further tasks that depend on it run, and the build exits non-zero. With --continue, Gradle keeps running every task whose dependencies still succeeded, then reports all failures together at the end.
solid answer
~40 sWhen a task's action throws, Gradle marks that task **FAILED**. The default policy is **fail-fast**: Gradle aborts the build as soon as the first failure occurs, skips any not-yet-started tasks, and exits with a non-zero status. Tasks already completed keep their outputs. With **`--continue`**, Gradle does not stop — it skips only the failed task's **dependents** (tasks that needed its output) and proceeds to execute every other scheduled task whose dependencies still succeeded. At the end it reports **all** collected failures together. This is especially useful in CI: a single run surfaces every failing module/test instead of forcing fix-one-rerun cycles. **Finalizers** declared via `finalizedBy` still run even when their finalized task fails — handy for cleanup or publishing reports. Note `--continue` never makes a failed build succeed; the exit code is still non-zero.
code
bash · 5 lines# Default: stops at first failing module
gradle build
# Run everything possible, report ALL failures together (still exits non-zero)
gradle build --continuego deeper
Say the build stops at the first failure by default and exits with an error.
Contrast fail-fast with --continue, noting dependents are skipped and all failures are reported at the end.
Explain finalizer-on-failure semantics and why --continue is valuable in CI for full failure visibility.
Discuss CI strategy: when to aggregate failures vs fail-fast, and how failure policy interacts with parallel multi-module pipelines.
## Default: fail-fast During Execution, if a task's `@TaskAction`/`doLast` throws an exception, that task is **FAILED**. By default Gradle: 1. Stops scheduling new tasks immediately. 2. Lets already-running tasks (in parallel mode) finish or abort per their state. 3. Prints the failure with `--stacktrace`/`--info` detail available. 4. Exits non-zero. Tasks that already ran keep their produced outputs (they aren't rolled back). ## `--continue` `gradle build --continue` changes the policy: Gradle keeps going. When a task fails, only the tasks that **depend on it** are skipped (their inputs would be missing/invalid); every other independent task still runs. All failures are aggregated and printed at the end: ``` bash> gradle test --continue ... FAILURE: Build completed with 3 failures. 1: Task :a:test FAILED 2: Task :b:test FAILED 3: Task :c:test FAILED ``` ### Why it matters In a multi-module build or a large test suite, fail-fast tells you about the *first* problem only. `--continue` gives the full picture in one run — a big CI time-saver. ## Finalizers and failure A task declared as a **finalizer** of T via `T.finalizedBy(F)` runs **even if T fails**. This is the idiomatic way to guarantee teardown (stop a server, collect logs, publish a test report) regardless of outcome: ```kotlin val startServer = tasks.register("startServer") val stopServer = tasks.register("stopServer") tasks.register("integTest") { dependsOn(startServer) finalizedBy(stopServer) // runs even if integTest fails } ``` ## What --continue does NOT do - It does **not** turn a failure into success — exit code stays non-zero. - It does **not** run tasks whose dependencies failed (their inputs are invalid). - It is orthogonal to up-to-date checking and parallelism. ## Related flags - `--stacktrace` / `--full-stacktrace` — more failure detail. - `--offline`, `--rerun-tasks` — unrelated to failure policy. - `org.gradle.parallel` — with parallel execution, multiple independent failures can occur in the same run even without `--continue`.
- Does `--continue` make the overall build succeed if some tasks failed?No. It only changes how much work runs; the build still fails with a non-zero exit code, aggregating all failures.
- If task A fails with `--continue`, what happens to a task B that has `dependsOn(A)`?B is skipped, because its dependency failed and its inputs would be invalid. Independent tasks still run.
- How do you guarantee a cleanup task runs even when the main task fails?Declare it as a finalizer with `mainTask.finalizedBy(cleanupTask)`; finalizers run regardless of the finalized task's success.
saying these in an interview costs you the question
- Saying `--continue` makes a failing build pass.
- Claiming finalizers are skipped when the finalized task fails.
- Thinking dependents of a failed task still run under --continue.