Maven build cache extension not restoring: the causes
You set up the Apache Maven Build Cache Extension against a self-hosted cache and the second build still compiles everything. Each cause below was reproduced for real. Find your symptom in the logs, then the fix.
First, what a healthy build looks like
The first build stores its result, and it looks alarming because Maven 3.10.0 logs a miss as an error (Maven 3.9.9 logs it as [INFO] Cache item not found):
[INFO] Attempting to restore project demo:demo from build cache
[ERROR] Error downloading cache item: https://cache.example.com//v1.1/demo/demo/ebb9bceba2f7a6bc/buildinfo.xml
[INFO] Saved to remote cache https://cache.example.com//v1.1/demo/demo/ebb9bceba2f7a6bc/demo.jar
[INFO] Saved to remote cache https://cache.example.com//v1.1/demo/demo/ebb9bceba2f7a6bc/buildinfo.xml
[INFO] BUILD SUCCESS
That [ERROR] line is only the server saying it does not have the entry. What matters is the Saved to remote cache lines after it. After deleting target and the extension's local cache folder, the second build:
[INFO] Attempting to restore project demo:demo from build cache
[INFO] Found cached build, restoring demo:demo from cache by checksum ebb9bceba2f7a6bc
[INFO] BUILD SUCCESS
You must delete the local folder to prove the remote works, because the extension keeps its own local cache and will use it first.
Symptom 1: Maven stops with "Unrecognised tag: 'remote'"
Cannot initialize cache because xml config is not valid or not available
Unable to parse cache xml element: Unrecognised tag: 'remote' ...
Cause: the remote element is outside configuration. Fix: move it inside, as in the working file below. Nothing built, and the server saw nothing.
Symptom 2: the build succeeds, but the server stays empty
There are no Saved to remote cache lines, the second build says "Remote cache is incomplete or missing", and the server's status page shows store_entries: 0.
Cause: without saveToRemote="true" the extension reads from the server and never uploads. Fix: add it on the machines that should upload, usually CI.
Symptom 3: "HTTP Status: 401" in the log, and still no uploads
org.eclipse.aether.spi.connector.transport.http.HttpTransporterException: HTTP Status: 401
The build still ends in BUILD SUCCESS, the server stays empty, and the lines Saved to remote cache are missing. In our runs we got exactly this from two different mistakes:
- the
idof the<server>insettings.xmldid not match theidon theremoteelement, and - the ids matched but the password was wrong.
Fix: make the two ids identical and check the password. Maven 3.10 may also print a warning about the credentials being used for an address without a matching repository entry. In our working setup the build behaved the same either way.
Maven build cache and different Java versions: Java 21 and Java 27
Nothing is broken here. The question is whether switching Java makes a cached build stop restoring.
- In our runs, a build cached on one Java was restored on the other, in both directions. Nothing was rebuilt.
- In our runs, the jar you get is the one the first build made. The manifest inside it names that Java:
Build-Jdk-Spec: 21orBuild-Jdk-Spec: 27. - Gradle behaved differently in our other run: a different Java ran its tasks again and made its own entries. See Gradle build cache hit rate low, cause 3.
- In our runs, the first build decided what everyone got. If a Java 21 build fills the cache, a Java 27 build restores a jar that says it was built on Java 21. Here that was harmless, because the class was identical. We did not test a project whose output depends on the Java that compiles it.
Our advice, not a test result: use one Java version for the builds that fill a shared cache, so you know which Java made what you restore.
For a multi-module project, see Maven build cache extension in a multi-module project.
The working configuration
<?xml version="1.0" encoding="UTF-8"?>
<cache xmlns="http://maven.apache.org/BUILD-CACHE-CONFIG/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/BUILD-CACHE-CONFIG/1.2.0 https://maven.apache.org/xsd/build-cache-config-1.2.0.xsd">
<configuration>
<enabled>true</enabled>
<remote enabled="true" saveToRemote="true" id="fosterstack-cache">
<url>https://cache.example.com/</url>
</remote>
</configuration>
</cache>
With a password on the server, ~/.m2/settings.xml needs a matching <server> entry with <id>fosterstack-cache</id>. The full walk-through is in Maven build cache extension: remote server setup.
Check the server's side
The status page counts what arrived. After the healthy first build it showed store_entries: 3, and after the restoring build cache_hits: 2. If those stay at zero while your builds run, the problem is between Maven and the server, not in the project. See the HTTP status codes.
How we checked
Symptom runs
Each cause above was reproduced with Maven 3.10.0, extension 1.2.3 and a 0.2.1 server with a password.
Java runs
A one-module Maven project, built five times in each of three series, with mvn verify and JAVA_HOME set for each build. For series B and C we saved mvn -v for every build to confirm which Java ran (series A has only its summary): Temurin 21.0.12.1 or OpenJDK 27 from Homebrew.
- Series A:
maven.compiler.releaseset to 17, first build on Java 21. - Series B: no
maven.compiler.release, first build on Java 21. - Series C: no
maven.compiler.release, first build on Java 27.
Every build used a fresh copy of the project and an empty local build cache. All builds ran on the same Mac, shared one already-filled local Maven repository (offline), and shared the cache server. Each series started on an empty server. Every build ended with BUILD SUCCESS.
| Build | Series B: Java | Series B: result | Series C: Java | Series C: result |
|---|---|---|---|---|
| 1 | 21 | Built | 27 | Built |
| 2 | 21 | Restored | 27 | Restored |
| 3 | 27 | Restored | 21 | Restored |
| 4 | 27 | Restored | 21 | Restored |
| 5 | 21 | Restored | 27 | Restored |
"Restored" means the log said Found cached build, restoring and Maven skipped the compile and test steps. Series A, with the release setting, gave the same pattern as series B.
In series B all five jars had one checksum, 0f4e29a2..., so the jar restored on Java 27 was the jar built on Java 21. In series C all five had another, ddb48271..., the jar built on Java 27. The files inside the two jars differ in a single place. The manifest in the first says Build-Jdk-Spec: 21 and in the second Build-Jdk-Spec: 27. The compiled class inside was byte-for-byte the same in both (we compared it with cmp). Without the release setting the compiler plugin still compiled for Java 8 on both Javas (the log said target 1.8), which is why the class was the same.
The Java runs used Maven 3.10.0 with maven-build-cache-extension 1.2.3 and FosterStack Cache 0.2.1, on macOS (arm64), with Temurin 21.0.12.1 and OpenJDK 27 (Homebrew).
Not tested in the symptom runs: other Maven versions, or extension 1.2.0. Not tested in the Java runs: other Maven or extension versions, other Java vendors, a project whose build settings change with the Java version (for example, profiles that switch on by JDK), and Windows. The second run, below, was on Linux.
Second run: Linux, 0.2.2
The runs above were on a Mac with 0.2.1. We ran this page again on a GitHub-hosted Linux machine with FosterStack Cache 0.2.2, Maven 3.10.0 (and 3.9.9 for one build), extension 1.2.3, Java 21, and Java 27 (Temurin) for the Java runs.
- In a healthy first build the miss showed as an
[ERROR]line and the server then held 3 entries. After we deletedtargetand the local cache folder, the second build loggedFound cached build, restoring demo:demo from cache by checksum, and the server counted 2 hits. - Maven 3.9.9 logged the miss as
[INFO] Cache item not found. - Symptom 1: Maven stopped with both log lines shown. Nothing was compiled or saved, and the server's hit, miss and entry counts stayed at 0.
- Symptom 2: the build succeeded with no
Saved to remote cacheline, the second build saidRemote cache is incomplete or missing, and the server held 0 entries. - Symptom 3: both mistakes (a different server id, and the right id with a wrong password) gave
HTTP Status: 401with the exception line shown above. The build still ended withBUILD SUCCESS, printed noSaved to remote cacheline and left the server empty. - With the wrong password, Maven also printed a warning that it used the server's credentials for an address with no repository or mirror of that id declared.
- Java runs, restores: in each of the three series only the first build compiled. The other four were restored, including the builds on the other Java.
- Java runs, jars: the five jars of a series had one checksum. Each manifest named the Java of the first build (21 in series A and B, 27 in series C).
- Java runs, class file: without the release setting, the log said
target 1.8on both Javas, and the compiled class in the two jars was byte for byte the same.
Every run here used a server without a password, except symptom 3. The Mac symptom runs used one with a password. The run and its log are public.