Das Symptom
mvn bricht ab, bevor es überhaupt zu kompilieren beginnt. Die Meldung spricht von einem Non-resolvable parent POM und nennt groupId, artifactId und version eines Elternprojekts, das Maven weder im Dateisystem noch im lokalen noch im entfernten Repository finden konnte. Das Elternprojekt liegt aber direkt daneben, die pom.xml ist da, und beim Kollegen baut es.
Gern tritt der Fehler nach einem Release auf, nach dem Umbau einer Ordnerstruktur, beim Auschecken eines einzelnen Moduls in der CI oder wenn jemand den parent-Block aus einem anderen Projekt kopiert hat.
Die „Layer 8“-Wahrheit
Maven sucht das Elternprojekt an genau drei Stellen, in fester Reihenfolge, und die Model-Referenz schreibt sie auf: „Maven looks for the parent POM first in this location on the filesystem, then the local repository, and lastly in the remote repo.“ Die Stelle im Dateisystem ist das Feld relativePath, und für dessen Vorgabe gilt: „If not specified, it defaults to ../pom.xml.“ Ein Modul, dessen Elternprojekt eine Ebene höher liegt, braucht also nichts anzugeben. Jede andere Anordnung braucht den Pfad ausdrücklich.
Der tückische Teil steht einen Satz weiter. Die Datei unter relativePath wird nur akzeptiert, wenn sie zu den Koordinaten passt: „However, the group ID, artifact ID and version are still required, and must match the file in the location given or it will revert to the repository for the POM.“ Stimmt die Version im parent-Block nicht mit der Version in der gefundenen Datei überein, verwirft Maven die Datei und fragt die Repositorys. Dort liegt die alte Version meist nicht, weil Elternprojekte in Multi-Modul-Builds selten einzeln installiert werden. Das Ergebnis ist die Meldung, die behauptet, das Elternprojekt sei unauffindbar, obwohl es im Nachbarordner liegt. Es liegt dort, es ist nur nicht das, was gesucht wird.
Die Referenz stuft die Dateisystemsuche als Entwicklungshilfe ein: „This feature is only for enhancing the development in a local checkout of that project.“ Daraus folgt auch, wann man sie abschaltet: „Set the value to an empty string in case you want to disable the feature and always resolve the parent POM from the repositories.“ Ein leerer relativePath ist richtig für ein firmenweites Parent-POM, das als eigenes Artefakt veröffentlicht wird. In einem Projekt, dessen Elternprojekt nie ein Repository sieht, ist derselbe leere Eintrag die Ursache des Fehlers, den er angeblich vermeiden sollte.
Ein Detail, das Platzhalter-Freunde trifft: Die Model-Referenz vermerkt zum parent-Element, dass seine Kinder nicht interpoliert werden und als Literale angegeben werden müssen. Eine Version, die über eine Property gesetzt wird, kommt im parent-Block nicht an.
Die Prüfung dauert eine Minute: parent-Block des Moduls neben die Kopfzeilen des Eltern-POM legen, drei Werte vergleichen, Pfad prüfen. Erst wenn alles stimmt und die Meldung bleibt, lohnt der Blick auf Repositorys, Spiegel und Netz.