# How Maven Resumes Builds After Failure: The Complete Technical Guide

> Learn how Maven resumes failed builds! Discover the technical details of persistence and reactor graph re-evaluation with the --resume flag.

- Repository: [The Apache Software Foundation/maven](https://github.com/apache/maven)
- Tags: deep-dive
- Published: 2026-07-05

---

**Maven resumes failed builds by persisting failure state to `target/resume.properties` and re-evaluating the reactor graph when invoked with `--resume` (`-r`), skipping modules that already succeeded.**

When a multi-module build fails in the `apache/maven` repository, developers don't need to rebuild everything from scratch. The **Maven build resumption** mechanism records the exact failure point and provides intelligent shortcuts to restart from where the build broke. This feature is implemented across the core execution engine and involves state persistence, validation logic, and reactor graph manipulation.

## Recording the Build Failure State

When Maven detects a build failure, it immediately serializes the current progress to disk. This creates a durable checkpoint that survives process termination.

### The resume.properties File

Upon failure, Maven writes a `resume.properties` file to the root project's `target` directory. This file contains:

- `resumeFrom`: The coordinates (groupId:artifactId) of the failed module
- `timestamp`: The ISO-8601 timestamp when the failure occurred

If the build succeeds, Maven automatically removes this file to prevent stale resume attempts.

### DefaultBuildResumptionDataRepository Implementation

The **`DefaultBuildResumptionDataRepository`** class in [`impl/maven-core/src/main/java/org/apache/maven/execution/DefaultBuildResumptionDataRepository.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/DefaultBuildResumptionDataRepository.java) handles this persistence. Its `store()` method writes the properties file only when the build ends with failures, while successful builds trigger file deletion. The repository ensures the selector stored includes the groupId when necessary to resolve ambiguous artifact IDs.

## Determining Resume Eligibility

Not every failed build can be resumed. Maven validates several preconditions before allowing the resume flag to take effect.

### BuildResumptionAnalyzer Interface

The **`BuildResumptionAnalyzer`** interface in [`impl/maven-core/src/main/java/org/apache/maven/execution/BuildResumptionAnalyzer.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/BuildResumptionAnalyzer.java) defines a single method that inspects `MavenExecutionResult` and returns an `Optional<BuildResumptionData>`. This abstraction allows the core to query whether resuming is technically possible before attempting graph manipulation.

### Validation Logic in DefaultBuildResumptionAnalyzer

The **`DefaultBuildResumptionAnalyzer`** implementation performs strict validation in [`impl/maven-core/src/main/java/org/apache/maven/execution/DefaultBuildResumptionAnalyzer.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/DefaultBuildResumptionAnalyzer.java). It checks that:

- The build actually failed
- The `resume.properties` file exists and is readable
- The execution involved a single reactor (multi-module builds only)
- The failed project is not the first module in the reactor

If any check fails, it returns `Optional.empty()` and sets `canResume()` to false in the execution result.

## Parsing the Resume Flag

User interaction with build resumption occurs through command-line options processed by the CLI layer.

### CLI Option Processing

The **`MavenCli`** class in [`impl/maven-cli/src/main/java/org/apache/maven/cli/MavenCli.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cli/MavenCli.java) parses `--resume` (`-r`) and `--resume-from` (`-rf`) via the **`CommonsCliMavenOptions`** class in [`impl/maven-cli/src/main/java/org/apache/maven/cli/CommonsCliMavenOptions.java`](https://github.com/apache/maven/blob/main/impl/maven-cli/src/main/java/org/apache/maven/cli/CommonsCliMavenOptions.java). When detected, these flags populate the execution request with specific resume instructions.

### MavenExecutionRequest Configuration

The **`MavenExecutionRequest`** interface and its implementation **`DefaultMavenExecutionRequest`** in [`impl/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/MavenExecutionRequest.java) and [`impl/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequest.java) store two critical fields:

- `resume`: Boolean flag indicating automatic resume mode
- `resumeFrom`: Optional string selector specifying manual resume coordinates

When `mvn -r` executes, `request.setResume(true)` is invoked, signaling the core to look for the properties file.

## Selecting the Resume Point

Once the resume flag is set, Maven must determine where in the reactor graph to begin execution.

### Graph Building and Project Selection

The **`DefaultGraphBuilder`** in [`impl/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/graph/DefaultGraphBuilder.java) reads the selector from `resume.properties` when `resume=true`. It locates the index of the specified module in the sorted project list, then creates a sub-list containing only the projects from that index forward. This trims the reactor to exclude already-successful modules.

If the selector cannot be found, Maven aborts with the error: `"Could not find project to resume reactor build from"`.

### Handling Manual resume-from

When users specify `--resume-from :module-name` manually, the CLI sets `request.setResumeFrom(":module-name")`. This bypasses the properties file entirely. The graph builder validates this selector against the available projects, ensuring the resume target exists before constructing the partial reactor.

## Executing the Partial Reactor

The actual execution of the trimmed module list occurs in the lifecycle engine.

The **`BuildPlanExecutor`** in [`impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/concurrent/BuildPlanExecutor.java`](https://github.com/apache/maven/blob/main/impl/maven-core/src/main/java/org/apache/maven/lifecycle/internal/concurrent/BuildPlanExecutor.java) receives the reduced project list and executes it exactly like a standard build. The executor logs diagnostic timing statistics under variables named `resumed` to track how much time was saved by skipping successful modules.

## Edge Cases and Error Handling

Maven's resume logic handles several failure scenarios gracefully:

- **First module failure**: No `resume.properties` is written because there are no successful modules to skip; `canResume()` returns false.
- **Multiple reactor execution**: If the build involved multiple separate reactor executions, resume is disabled automatically.
- **Missing resume.properties**: If the file is deleted or unreadable, Maven logs a warning and ignores the `-r` flag.
- **Ambiguous selectors**: When artifact IDs collide across group IDs, Maven stores the full `groupId:artifactId` coordinate to ensure unique identification.
- **Invalid manual selectors**: Attempting to resume from a non-existent module results in an immediate error before any build execution starts.

## Practical Usage Examples

Below is the typical workflow for utilizing **Maven build resumption**.

First, run a build that fails in a multi-module project:

```bash
mvn clean install

# Build fails in module-b after module-a succeeds

```

Maven automatically creates `target/resume.properties`:

```properties
resumeFrom=com.example:module-b
timestamp=2026-07-05T14:23:12.345Z

```

Resume the build automatically:

```bash
mvn -r clean install

```

Or manually specify a resume point without the properties file:

```bash
mvn -rf :module-c clean install

```

Internally, this sets the resume parameters:

```java
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
request.setResume(true);           // From -r flag
request.setResumeFrom(null);       // Auto-detect from resume.properties

```

## Summary

- **Maven build resumption** persists failure state to `target/resume.properties` via **`DefaultBuildResumptionDataRepository`**.
- The **`DefaultBuildResumptionAnalyzer`** validates that resuming is possible before allowing execution.
- The **`MavenCli`** layer parses `--resume` (`-r`) and `--resume-from` (`-rf`) into **`MavenExecutionRequest`** flags.
- **`DefaultGraphBuilder`** trims the reactor graph to exclude already-successful modules based on the stored selector.
- **`BuildPlanExecutor`** runs the reduced build plan while logging resumed execution statistics.
- Edge cases like first-module failures, missing files, and ambiguous selectors are handled with clear warnings or errors.

## Frequently Asked Questions

### What is the difference between --resume and --resume-from in Maven?

The **`--resume`** (`-r`) flag automatically reads the `resume.properties` file generated by a previous failed build and resumes from the exact failure point. The **`--resume-from`** (`-rf`) flag allows you to manually specify a module coordinate (like `:module-name`) to resume from, bypassing the automatic state detection. Use `-r` for automatic resumption after fixing the failure, and `-rf` when you want to start from a specific module regardless of previous state.

### Where does Maven store the resume state?

Maven stores the resume state in a file named `resume.properties` located in the `target` directory of the root project. This file is written by **`DefaultBuildResumptionDataRepository`** only when a build fails, and it contains the `resumeFrom` selector (typically `groupId:artifactId`) and a timestamp. Successful builds automatically delete this file to prevent stale resumptions.

### Can Maven resume a build if the first module fails?

No. Maven cannot resume a build if the first module in the reactor fails because there are no successful modules to skip. The **`DefaultBuildResumptionAnalyzer`** explicitly checks that the failed project is not the first one before writing `resume.properties` or allowing `canResume()` to return true. In this scenario, you must fix the issue and run the full build again.

### How does Maven handle duplicate artifact IDs when resuming?

When multiple modules share the same artifact ID but different group IDs, Maven resolves the ambiguity by storing the full coordinate `groupId:artifactId` in the `resumeFrom` field of `resume.properties`. The **`DefaultBuildResumptionDataRepository`** enriches the selector with the group ID when necessary, ensuring that **`DefaultGraphBuilder`** can uniquely identify the correct module in the reactor graph.